Преглед на файлове

simplified direct-volume renderable (merged 2d and 3d version)

Alexander Rose преди 6 години
родител
ревизия
02892d7d67

+ 58 - 127
src/mol-geo/geometry/direct-volume/direct-volume.ts

@@ -8,8 +8,8 @@ import { RuntimeContext } from 'mol-task'
 import { ValueCell } from 'mol-util'
 import { Sphere3D, Box3D } from 'mol-math/geometry'
 import { paramDefaultValues, RangeParam, SelectParam, TextParam } from 'mol-view/parameter';
-import { DirectVolume2dValues, DirectVolumeBaseValues, DirectVolume3dValues } from 'mol-gl/renderable/direct-volume';
-import { Vec3, Vec2, Mat4 } from 'mol-math/linear-algebra';
+import { DirectVolumeValues } from 'mol-gl/renderable/direct-volume';
+import { Vec3, Mat4 } from 'mol-math/linear-algebra';
 import { Box } from '../../primitive/box';
 import { getControlPointsFromString, createTransferFunctionTexture } from './transfer-function';
 import { Texture } from 'mol-gl/webgl/texture';
@@ -22,7 +22,10 @@ import { Geometry } from '../geometry';
 const VolumeBox = Box()
 const RenderModeOptions = [['isosurface', 'Isosurface'], ['volume', 'Volume']] as [string, string][]
 
-interface DirectVolumeBase {
+export interface DirectVolume {
+    readonly kind: 'direct-volume',
+    readonly gridTexture: ValueCell<Texture>,
+    readonly gridTextureDim: ValueCell<Vec3>,
     readonly gridDimension: ValueCell<Vec3>,
     readonly bboxSize: ValueCell<Vec3>
     readonly bboxMin: ValueCell<Vec3>
@@ -33,74 +36,12 @@ interface DirectVolumeBase {
     boundingSphere?: Sphere3D
 }
 
-const BaseParams = {
-    ...Geometry.Params,
-    isoValueAbsolute: RangeParam('Iso Value Absolute', '', 0.22, -1, 1, 0.01),
-    isoValueRelative: RangeParam('Iso Value Relative', '', 2, -10, 10, 0.1),
-    renderMode: SelectParam('Render Mode', '', 'isosurface', RenderModeOptions),
-    controlPoints: TextParam('Control Points', '', '0.19:0.1, 0.2:0.5, 0.21:0.1, 0.4:0.3'),
-}
-const DefaultBaseProps = paramDefaultValues(BaseParams)
-type BaseProps = typeof DefaultBaseProps
-
-async function createBaseValues(ctx: RuntimeContext, directVolume: DirectVolumeBase, transform: TransformData, locationIt: LocationIterator, props: BaseProps): Promise<DirectVolumeBaseValues> {
-    const { instanceCount, groupCount } = locationIt
-    const color = await createColors(ctx, locationIt, props)
-    const marker = createMarkers(instanceCount * groupCount)
-
-    const counts = { drawCount: VolumeBox.indices.length, groupCount, instanceCount }
-
-    const { bboxSize, bboxMin, bboxMax, gridDimension, transform: gridTransform } = directVolume
-
-    const controlPoints = getControlPointsFromString(props.controlPoints)
-    const transferTex = createTransferFunctionTexture(controlPoints)
-
-    const maxSteps = Math.ceil(Vec3.magnitude(gridDimension.ref.value)) * 2
-
-    return {
-        ...color,
-        ...marker,
-        ...transform,
-        ...Geometry.createValues(props, counts),
-
-        aPosition: ValueCell.create(VolumeBox.vertices as Float32Array),
-        elements: ValueCell.create(VolumeBox.indices as Uint32Array),
-
-        uIsoValue: ValueCell.create(props.isoValueAbsolute),
-        uBboxMin: bboxMin,
-        uBboxMax: bboxMax,
-        uBboxSize: bboxSize,
-        dMaxSteps: ValueCell.create(maxSteps),
-        uTransform: gridTransform,
-        uGridDim: gridDimension,
-        dRenderMode: ValueCell.create(props.renderMode),
-        tTransferTex: transferTex,
-    }
-}
-
-function updateBaseValues(values: DirectVolumeBaseValues, props: BaseProps) {
-    ValueCell.updateIfChanged(values.uIsoValue, props.isoValueAbsolute)
-    ValueCell.updateIfChanged(values.uAlpha, props.alpha)
-    ValueCell.updateIfChanged(values.dUseFog, props.useFog)
-    ValueCell.updateIfChanged(values.dRenderMode, props.renderMode)
-
-    const controlPoints = getControlPointsFromString(props.controlPoints)
-    createTransferFunctionTexture(controlPoints, values.tTransferTex)
-}
-
-// 2d
-
-export interface DirectVolume2d extends DirectVolumeBase {
-    readonly kind: 'direct-volume-2d',
-    readonly gridTexture: ValueCell<Texture>,
-    readonly gridTextureDim: ValueCell<Vec2>,
-}
-
-export namespace DirectVolume2d {
-    export function create(bbox: Box3D, gridDimension: Vec3, transform: Mat4, texture: Texture, directVolume?: DirectVolume2d): DirectVolume2d {
+export namespace DirectVolume {
+    export function create(bbox: Box3D, gridDimension: Vec3, transform: Mat4, texture: Texture, directVolume?: DirectVolume): DirectVolume {
+        const { width, height, depth } = texture
         if (directVolume) {
             ValueCell.update(directVolume.gridDimension, gridDimension)
-            ValueCell.update(directVolume.gridTextureDim, Vec2.set(directVolume.gridTextureDim.ref.value, texture.width, texture.height))
+            ValueCell.update(directVolume.gridTextureDim, Vec3.set(directVolume.gridTextureDim.ref.value, width, height, depth))
             ValueCell.update(directVolume.bboxMin, bbox.min)
             ValueCell.update(directVolume.bboxMax, bbox.max)
             ValueCell.update(directVolume.bboxSize, Vec3.sub(directVolume.bboxSize.ref.value, bbox.max, bbox.min))
@@ -108,10 +49,10 @@ export namespace DirectVolume2d {
             return directVolume
         } else {
             return {
-                kind: 'direct-volume-2d' as 'direct-volume-2d',
+                kind: 'direct-volume',
                 gridDimension: ValueCell.create(gridDimension),
                 gridTexture: ValueCell.create(texture),
-                gridTextureDim: ValueCell.create(Vec2.create(texture.width, texture.height)),
+                gridTextureDim: ValueCell.create(Vec3.create(width, height, depth)),
                 bboxMin: ValueCell.create(bbox.min),
                 bboxMax: ValueCell.create(bbox.max),
                 bboxSize: ValueCell.create(Vec3.sub(Vec3.zero(), bbox.max, bbox.min)),
@@ -120,78 +61,68 @@ export namespace DirectVolume2d {
         }
     }
 
-    export function createEmpty(directVolume?: DirectVolume2d): DirectVolume2d {
-        return {} as DirectVolume2d // TODO
+    export function createEmpty(directVolume?: DirectVolume): DirectVolume {
+        return {} as DirectVolume // TODO
     }
 
-    export const Params = BaseParams
+    export const Params = {
+        ...Geometry.Params,
+        isoValueAbsolute: RangeParam('Iso Value Absolute', '', 0.22, -1, 1, 0.01),
+        isoValueRelative: RangeParam('Iso Value Relative', '', 2, -10, 10, 0.1),
+        renderMode: SelectParam('Render Mode', '', 'isosurface', RenderModeOptions),
+        controlPoints: TextParam('Control Points', '', '0.19:0.1, 0.2:0.5, 0.21:0.1, 0.4:0.3'),
+    }
     export const DefaultProps = paramDefaultValues(Params)
     export type Props = typeof DefaultProps
 
-    export async function createValues(ctx: RuntimeContext, directVolume: DirectVolume2d, transform: TransformData, locationIt: LocationIterator, props: Props): Promise<DirectVolume2dValues> {
+    export async function createValues(ctx: RuntimeContext, directVolume: DirectVolume, transform: TransformData, locationIt: LocationIterator, props: Props): Promise<DirectVolumeValues> {
         const { gridTexture, gridTextureDim } = directVolume
 
-        return {
-            ...await createBaseValues(ctx, directVolume, transform, locationIt, props),
-            dGridTexType: ValueCell.create('2d'),
-            uGridTexDim: gridTextureDim,
-            tGridTex: gridTexture,
-        }
-    }
-
-    export function updateValues(values: DirectVolume2dValues, props: Props) {
-        updateBaseValues(values, props)
-    }
-}
-
-// 3d
+        const { instanceCount, groupCount } = locationIt
+        const color = await createColors(ctx, locationIt, props)
+        const marker = createMarkers(instanceCount * groupCount)
 
-export interface DirectVolume3d extends DirectVolumeBase {
-    readonly kind: 'direct-volume-3d',
-    readonly gridTexture: ValueCell<Texture>,
-}
-
-export namespace DirectVolume3d {
-    export function create(bbox: Box3D, gridDimension: Vec3, transform: Mat4, texture: Texture, directVolume?: DirectVolume3d): DirectVolume3d {
-        if (directVolume) {
-            ValueCell.update(directVolume.gridDimension, gridDimension)
-            ValueCell.update(directVolume.bboxMin, bbox.min)
-            ValueCell.update(directVolume.bboxMax, bbox.max)
-            ValueCell.update(directVolume.bboxSize, Vec3.sub(directVolume.bboxSize.ref.value, bbox.max, bbox.min))
-            ValueCell.update(directVolume.transform, transform)
-            return directVolume
-        } else {
-            return {
-                kind: 'direct-volume-3d' as 'direct-volume-3d',
-                gridDimension: ValueCell.create(gridDimension),
-                gridTexture: ValueCell.create(texture),
-                bboxMin: ValueCell.create(bbox.min),
-                bboxMax: ValueCell.create(bbox.max),
-                bboxSize: ValueCell.create(Vec3.sub(Vec3.zero(), bbox.max, bbox.min)),
-                transform: ValueCell.create(transform),
-            }
-        }
-    }
+        const counts = { drawCount: VolumeBox.indices.length, groupCount, instanceCount }
 
-    export function createEmpty(directVolume?: DirectVolume3d): DirectVolume3d {
-        return {} as DirectVolume3d // TODO
-    }
+        const { bboxSize, bboxMin, bboxMax, gridDimension, transform: gridTransform } = directVolume
 
-    export const Params = BaseParams
-    export const DefaultProps = paramDefaultValues(Params)
-    export type Props = typeof DefaultProps
+        const controlPoints = getControlPointsFromString(props.controlPoints)
+        const transferTex = createTransferFunctionTexture(controlPoints)
 
-    export async function createValues(ctx: RuntimeContext, directVolume: DirectVolume3d, transform: TransformData, locationIt: LocationIterator, props: Props): Promise<DirectVolume3dValues> {
-        const { gridTexture } = directVolume
+        const maxSteps = Math.ceil(Vec3.magnitude(gridDimension.ref.value)) * 2
 
         return {
-            ...await createBaseValues(ctx, directVolume, transform, locationIt, props),
-            dGridTexType: ValueCell.create('3d'),
+            ...color,
+            ...marker,
+            ...transform,
+            ...Geometry.createValues(props, counts),
+
+            aPosition: ValueCell.create(VolumeBox.vertices as Float32Array),
+            elements: ValueCell.create(VolumeBox.indices as Uint32Array),
+
+            uIsoValue: ValueCell.create(props.isoValueAbsolute),
+            uBboxMin: bboxMin,
+            uBboxMax: bboxMax,
+            uBboxSize: bboxSize,
+            dMaxSteps: ValueCell.create(maxSteps),
+            uTransform: gridTransform,
+            uGridDim: gridDimension,
+            dRenderMode: ValueCell.create(props.renderMode),
+            tTransferTex: transferTex,
+
+            dGridTexType: ValueCell.create(gridTexture.ref.value.depth > 0 ? '3d' : '2d'),
+            uGridTexDim: gridTextureDim,
             tGridTex: gridTexture,
         }
     }
 
-    export function updateValues(values: DirectVolume3dValues, props: Props) {
-        updateBaseValues(values, props)
+    export function updateValues(values: DirectVolumeValues, props: Props) {
+        ValueCell.updateIfChanged(values.uIsoValue, props.isoValueAbsolute)
+        ValueCell.updateIfChanged(values.uAlpha, props.alpha)
+        ValueCell.updateIfChanged(values.dUseFog, props.useFog)
+        ValueCell.updateIfChanged(values.dRenderMode, props.renderMode)
+
+        const controlPoints = getControlPointsFromString(props.controlPoints)
+        createTransferFunctionTexture(controlPoints, values.tTransferTex)
     }
 }

+ 3 - 5
src/mol-geo/geometry/geometry.ts

@@ -17,7 +17,7 @@ import { SizeType } from './size-data';
 import { Lines } from './lines/lines';
 import { paramDefaultValues, RangeParam, BooleanParam, SelectParam, ColorParam, StructureParam, ValueParam } from 'mol-view/parameter'
 import { Structure } from 'mol-model/structure';
-import { DirectVolume2d, DirectVolume3d } from './direct-volume/direct-volume';
+import { DirectVolume } from './direct-volume/direct-volume';
 import { Context } from 'mol-gl/webgl/context';
 
 //
@@ -43,8 +43,7 @@ export type GeometryKindType = {
     'mesh': Mesh,
     'points': Points,
     'lines': Lines,
-    'direct-volume-2d': DirectVolume2d,
-    'direct-volume-3d': DirectVolume3d
+    'direct-volume': DirectVolume,
 }
 export type GeometryKind = keyof GeometryKindType
 export type Geometry = Helpers.ValueOf<GeometryKindType>
@@ -55,8 +54,7 @@ export namespace Geometry {
             case 'mesh': return geometry.triangleCount * 3
             case 'points': return geometry.pointCount
             case 'lines': return geometry.lineCount * 2 * 3
-            case 'direct-volume-2d': return 12 * 3
-            case 'direct-volume-3d': return 12 * 3
+            case 'direct-volume': return 12 * 3
         }
     }
 

+ 2 - 3
src/mol-geo/representation/structure/index.ts

@@ -14,7 +14,7 @@ import { Mesh } from '../../geometry/mesh/mesh';
 import { Points } from '../../geometry/points/points';
 import { Lines } from '../../geometry/lines/lines';
 import { SelectParam, paramDefaultValues } from 'mol-view/parameter';
-import { DirectVolume2d, DirectVolume3d } from '../../geometry/direct-volume/direct-volume';
+import { DirectVolume } from '../../geometry/direct-volume/direct-volume';
 
 export interface StructureRepresentation<P extends RepresentationProps = {}> extends Representation<Structure, P> { }
 
@@ -48,8 +48,7 @@ export const DefaultStructureLinesProps = paramDefaultValues(StructureLinesParam
 export type StructureLinesProps = typeof DefaultStructureLinesProps
 
 export const StructureDirectVolumeParams = {
-    ...DirectVolume2d.Params,
-    ...DirectVolume3d.Params,
+    ...DirectVolume.Params,
     ...StructureParams,
 }
 export const DefaultStructureDirectVolumeProps = paramDefaultValues(StructureDirectVolumeParams)

+ 8 - 16
src/mol-geo/representation/structure/units-visual.ts

@@ -15,7 +15,7 @@ import { LocationIterator } from '../../util/location-iterator';
 import { Mesh } from '../../geometry/mesh/mesh';
 import { MarkerAction, applyMarkerAction, createMarkers } from '../../geometry/marker-data';
 import { Loci, isEveryLoci, EmptyLoci } from 'mol-model/loci';
-import { MeshRenderObject, PointsRenderObject, LinesRenderObject, DirectVolume2dRenderObject, DirectVolume3dRenderObject } from 'mol-gl/render-object';
+import { MeshRenderObject, PointsRenderObject, LinesRenderObject, DirectVolumeRenderObject } from 'mol-gl/render-object';
 import { createUnitsMeshRenderObject, createUnitsPointsRenderObject, createUnitsTransform, createUnitsLinesRenderObject, createUnitsDirectVolumeRenderObject } from './visual/util/common';
 import { deepEqual, ValueCell, UUID } from 'mol-util';
 import { Interval } from 'mol-data/int';
@@ -25,7 +25,7 @@ import { createColors, ColorProps } from '../../geometry/color-data';
 import { createSizes, SizeProps } from '../../geometry/size-data';
 import { Lines } from '../../geometry/lines/lines';
 import { MultiSelectParam, paramDefaultValues } from 'mol-view/parameter';
-import { DirectVolume2d, DirectVolume3d } from '../../geometry/direct-volume/direct-volume';
+import { DirectVolume } from '../../geometry/direct-volume/direct-volume';
 
 export const UnitKindInfo = {
     'atomic': {},
@@ -526,15 +526,15 @@ export const UnitsDirectVolumeParams = {
 }
 export const DefaultUnitsDirectVolumeProps = paramDefaultValues(UnitsDirectVolumeParams)
 export type UnitsDirectVolumeProps = typeof DefaultUnitsDirectVolumeProps
-export interface UnitsDirectVolumeVisualBuilder<P extends UnitsDirectVolumeProps> extends UnitsVisualBuilder<P, DirectVolume2d | DirectVolume3d> { }
+export interface UnitsDirectVolumeVisualBuilder<P extends UnitsDirectVolumeProps> extends UnitsVisualBuilder<P, DirectVolume> { }
 
 export function UnitsDirectVolumeVisual<P extends UnitsDirectVolumeProps>(builder: UnitsDirectVolumeVisualBuilder<P>): UnitsVisual<P> {
     const { defaultProps, createGeometry, createLocationIterator, getLoci, mark, setUpdateState } = builder
     const updateState = VisualUpdateState.create()
 
-    let renderObject: DirectVolume2dRenderObject | DirectVolume3dRenderObject | undefined
+    let renderObject: DirectVolumeRenderObject | undefined
     let currentProps: P
-    let directVolume: DirectVolume2d | DirectVolume3d
+    let directVolume: DirectVolume
     let currentGroup: Unit.SymmetryGroup
     let currentStructure: Structure
     let locationIt: LocationIterator
@@ -551,9 +551,7 @@ export function UnitsDirectVolumeVisual<P extends UnitsDirectVolumeProps>(builde
         currentConformationId = Unit.conformationId(unit)
         directVolume = includesUnitKind(currentProps.unitKinds, unit)
             ? await createGeometry(ctx, unit, currentStructure, currentProps, directVolume)
-            : (webgl.isWebGL2 ?
-                DirectVolume2d.createEmpty(directVolume as DirectVolume2d) :
-                DirectVolume3d.createEmpty(directVolume as DirectVolume3d))
+            : DirectVolume.createEmpty(directVolume)
 
         // TODO create empty location iterator when not in unitKinds
         locationIt = createLocationIterator(group)
@@ -598,9 +596,7 @@ export function UnitsDirectVolumeVisual<P extends UnitsDirectVolumeProps>(builde
         if (updateState.createGeometry) {
             directVolume = includesUnitKind(newProps.unitKinds, unit)
                 ? await createGeometry(ctx, unit, currentStructure, newProps, directVolume)
-                : (webgl.isWebGL2 ?
-                    DirectVolume2d.createEmpty(directVolume as DirectVolume2d) :
-                    DirectVolume3d.createEmpty(directVolume as DirectVolume3d))
+                : DirectVolume.createEmpty(directVolume)
             updateState.updateColor = true
         }
 
@@ -608,11 +604,7 @@ export function UnitsDirectVolumeVisual<P extends UnitsDirectVolumeProps>(builde
             await createColors(ctx, locationIt, newProps, renderObject.values)
         }
 
-        if (renderObject.type === 'direct-volume-2d') {
-            DirectVolume2d.updateValues(renderObject.values, newProps)
-        } else {
-            DirectVolume3d.updateValues(renderObject.values, newProps)
-        }
+        DirectVolume.updateValues(renderObject.values, newProps)
         updateRenderableState(renderObject.state, newProps)
 
         currentProps = newProps

+ 3 - 7
src/mol-geo/representation/structure/visual/gaussian-density-volume.ts

@@ -11,9 +11,9 @@ import { UnitsDirectVolumeVisual, UnitsDirectVolumeParams } from '../units-visua
 import { StructureElementIterator, getElementLoci, markElement } from './util/element';
 import { GaussianDensityProps, GaussianDensityParams, computeUnitGaussianDensityTexture } from 'mol-model/structure/structure/unit/gaussian-density';
 import { paramDefaultValues } from 'mol-view/parameter';
-import { DirectVolume2d, DirectVolume3d } from '../../../geometry/direct-volume/direct-volume';
+import { DirectVolume } from '../../../geometry/direct-volume/direct-volume';
 
-async function createGaussianDensityVolume(ctx: RuntimeContext, unit: Unit, structure: Structure, props: GaussianDensityProps, directVolume?: DirectVolume2d | DirectVolume3d): Promise<DirectVolume2d | DirectVolume3d> {
+async function createGaussianDensityVolume(ctx: RuntimeContext, unit: Unit, structure: Structure, props: GaussianDensityProps, directVolume?: DirectVolume): Promise<DirectVolume> {
     const { webgl } = props
     if (webgl === undefined) throw new Error('createGaussianDensityVolume requires `webgl` in props')
 
@@ -22,11 +22,7 @@ async function createGaussianDensityVolume(ctx: RuntimeContext, unit: Unit, stru
     const densityTextureData = await computeUnitGaussianDensityTexture(unit, p, oldTexture).runInContext(ctx)
     const { transform, texture, bbox, gridDimension } = densityTextureData
 
-    directVolume = texture.depth === 0 ?
-        DirectVolume2d.create(bbox, gridDimension, transform, texture, directVolume as DirectVolume2d) :
-        DirectVolume3d.create(bbox, gridDimension, transform, texture, directVolume as DirectVolume3d)
-
-    return directVolume;
+    return DirectVolume.create(bbox, gridDimension, transform, texture, directVolume)
 }
 
 export const GaussianDensityVolumeParams = {

+ 6 - 8
src/mol-geo/representation/structure/visual/util/common.ts

@@ -8,14 +8,14 @@ import { Unit, Structure } from 'mol-model/structure';
 import { LocationIterator } from '../../../../util/location-iterator';
 import { Mesh } from '../../../../geometry/mesh/mesh';
 import { StructureProps } from '../..';
-import { createMeshRenderObject, createPointsRenderObject, createLinesRenderObject, createDirectVolume2dRenderObject, createDirectVolume3dRenderObject } from 'mol-gl/render-object';
+import { createMeshRenderObject, createPointsRenderObject, createLinesRenderObject, createDirectVolumeRenderObject } from 'mol-gl/render-object';
 import { RuntimeContext } from 'mol-task';
 import { TransformData, createIdentityTransform, createTransform } from '../../../../geometry/transform-data';
 import { Points } from '../../../../geometry/points/points';
 import { createRenderableState } from '../../../../geometry/geometry';
 import { Mat4 } from 'mol-math/linear-algebra';
 import { Lines } from '../../../../geometry/lines/lines';
-import { DirectVolume2d, DirectVolume3d } from '../../../../geometry/direct-volume/direct-volume';
+import { DirectVolume } from '../../../../geometry/direct-volume/direct-volume';
 
 export function createUnitsTransform({ units }: Unit.SymmetryGroup, transformData?: TransformData) {
     const unitCount = units.length
@@ -63,19 +63,17 @@ type StructureLinesProps = Lines.Props & StructureProps
 export async function createUnitsLinesRenderObject(ctx: RuntimeContext, group: Unit.SymmetryGroup, lines: Lines, locationIt: LocationIterator, props: StructureLinesProps) {
     const transform = createUnitsTransform(group)
     const values = await Lines.createValues(ctx, lines, transform, locationIt, props)
-    console.log('values', values)
     const state = createRenderableState(props)
     return createLinesRenderObject(values, state)
 }
 
 // direct-volume
 
-type StructureDirectVolumeProps = DirectVolume2d.Props & DirectVolume3d.Props & StructureProps
+type StructureDirectVolumeProps = DirectVolume.Props & StructureProps
 
-export async function createUnitsDirectVolumeRenderObject(ctx: RuntimeContext, group: Unit.SymmetryGroup, directVolume: DirectVolume2d | DirectVolume3d, locationIt: LocationIterator, props: StructureDirectVolumeProps) {
+export async function createUnitsDirectVolumeRenderObject(ctx: RuntimeContext, group: Unit.SymmetryGroup, directVolume: DirectVolume, locationIt: LocationIterator, props: StructureDirectVolumeProps) {
     const transform = createUnitsTransform(group)
+    const values = await DirectVolume.createValues(ctx, directVolume, transform, locationIt, props)
     const state = createRenderableState(props)
-    return directVolume.kind === 'direct-volume-2d' ?
-        createDirectVolume2dRenderObject(await DirectVolume2d.createValues(ctx, directVolume, transform, locationIt, props), state) :
-        createDirectVolume3dRenderObject(await DirectVolume3d.createValues(ctx, directVolume, transform, locationIt, props), state)
+    return createDirectVolumeRenderObject(values, state)
 }

+ 16 - 22
src/mol-geo/representation/volume/direct-volume.ts

@@ -7,17 +7,16 @@
 import { VolumeData } from 'mol-model/volume'
 import { RuntimeContext } from 'mol-task'
 import { VolumeVisual, VolumeRepresentation } from '.';
-import { DirectVolume2dRenderObject, createDirectVolume2dRenderObject, DirectVolume3dRenderObject, createDirectVolume3dRenderObject } from 'mol-gl/render-object';
+import { DirectVolumeRenderObject, createDirectVolumeRenderObject } from 'mol-gl/render-object';
 import { PickingId } from '../../geometry/picking';
 import { MarkerAction } from '../../geometry/marker-data';
 import { Loci, EmptyLoci } from 'mol-model/loci';
 import { createRenderableState, updateRenderableState, Geometry } from '../../geometry/geometry';
 import { paramDefaultValues } from 'mol-view/parameter';
-import { DirectVolume2d, DirectVolume3d } from '../../geometry/direct-volume/direct-volume';
+import { DirectVolume } from '../../geometry/direct-volume/direct-volume';
 import { Vec3, Mat4 } from 'mol-math/linear-algebra';
 import { Box3D } from 'mol-math/geometry';
 import { Context } from 'mol-gl/webgl/context';
-import { DirectVolume3dValues, DirectVolume2dValues } from 'mol-gl/renderable/direct-volume';
 import { createTexture } from 'mol-gl/webgl/texture';
 import { LocationIterator } from 'mol-geo/util/location-iterator';
 import { NullLocation } from 'mol-model/location';
@@ -86,7 +85,7 @@ function createVolumeTexture2d(volume: VolumeData, maxTextureSize: number) {
     return textureImage
 }
 
-export function createDirectVolume2d(ctx: RuntimeContext, webgl: Context, volume: VolumeData, directVolume?: DirectVolume2d) {
+export function createDirectVolume2d(ctx: RuntimeContext, webgl: Context, volume: VolumeData, directVolume?: DirectVolume) {
     const gridDimension = volume.data.space.dimensions as Vec3
     const textureImage = createVolumeTexture2d(volume, webgl.maxTextureSize)
     // debugTexture(createImageData(textureImage.array, textureImage.width, textureImage.height), 1/3)
@@ -99,7 +98,7 @@ export function createDirectVolume2d(ctx: RuntimeContext, webgl: Context, volume
     const texture = directVolume ? directVolume.gridTexture.ref.value : createTexture(webgl, 'image-uint8', 'rgba', 'ubyte', 'linear')
     texture.load(textureImage)
 
-    return DirectVolume2d.create(bbox, dim, transform, texture, directVolume)
+    return DirectVolume.create(bbox, dim, transform, texture, directVolume)
 }
 
 // 3d volume texture
@@ -126,7 +125,7 @@ function createVolumeTexture3d(volume: VolumeData) {
     return textureVolume
 }
 
-export function createDirectVolume3d(ctx: RuntimeContext, webgl: Context, volume: VolumeData, directVolume?: DirectVolume3d) {
+export function createDirectVolume3d(ctx: RuntimeContext, webgl: Context, volume: VolumeData, directVolume?: DirectVolume) {
     const gridDimension = volume.data.space.dimensions as Vec3
     const textureVolume = createVolumeTexture3d(volume)
     const transform = VolumeData.getGridToCartesianTransform(volume)
@@ -135,23 +134,23 @@ export function createDirectVolume3d(ctx: RuntimeContext, webgl: Context, volume
     const texture = directVolume ? directVolume.gridTexture.ref.value : createTexture(webgl, 'volume-uint8', 'rgba', 'ubyte', 'linear')
     texture.load(textureVolume)
 
-    return DirectVolume3d.create(bbox, gridDimension, transform, texture, directVolume)
+    return DirectVolume.create(bbox, gridDimension, transform, texture, directVolume)
 }
 
 //
 
 export const DirectVolumeParams = {
     ...Geometry.Params,
-    ...DirectVolume2d.Params
+    ...DirectVolume.Params
 }
 export const DefaultDirectVolumeProps = paramDefaultValues(DirectVolumeParams)
 export type DirectVolumeProps = typeof DefaultDirectVolumeProps
 
 export function DirectVolumeVisual(): VolumeVisual<DirectVolumeProps> {
     let currentProps = DefaultDirectVolumeProps
-    let renderObject: DirectVolume2dRenderObject | DirectVolume3dRenderObject
+    let renderObject: DirectVolumeRenderObject
     let currentVolume: VolumeData
-    let directVolume: DirectVolume2d | DirectVolume3d
+    let directVolume: DirectVolume
 
     async function create(ctx: RuntimeContext, volume: VolumeData, props: Partial<DirectVolumeProps> = {}) {
         const { webgl } = props
@@ -167,14 +166,13 @@ export function DirectVolumeVisual(): VolumeVisual<DirectVolumeProps> {
         const transform = createIdentityTransform()
 
         if (webgl.isWebGL2) {
-            console.log('creating 3d volume')
-            directVolume = await createDirectVolume3d(ctx, webgl, volume, directVolume as DirectVolume3d)
-            const values = await DirectVolume3d.createValues(ctx, directVolume as DirectVolume3d, transform, locationIt, currentProps)
-            renderObject = createDirectVolume3dRenderObject(values, state)
+            directVolume = await createDirectVolume3d(ctx, webgl, volume, directVolume)
+            const values = await DirectVolume.createValues(ctx, directVolume, transform, locationIt, currentProps)
+            renderObject = createDirectVolumeRenderObject(values, state)
         } else {
-            directVolume = await createDirectVolume2d(ctx, webgl, volume, directVolume as DirectVolume2d)
-            const values = await DirectVolume2d.createValues(ctx, directVolume as DirectVolume2d, transform, locationIt, currentProps)
-            renderObject = createDirectVolume2dRenderObject(values, state)
+            directVolume = await createDirectVolume2d(ctx, webgl, volume, directVolume)
+            const values = await DirectVolume.createValues(ctx, directVolume, transform, locationIt, currentProps)
+            renderObject = createDirectVolumeRenderObject(values, state)
         }
     }
 
@@ -187,11 +185,7 @@ export function DirectVolumeVisual(): VolumeVisual<DirectVolumeProps> {
             // newProps.isoValueAbsolute = VolumeIsoValue.calcAbsolute(currentVolume.dataStats, props.isoValueRelative)
         }
 
-        if (webgl.isWebGL2) {
-            DirectVolume3d.updateValues(renderObject.values as DirectVolume3dValues, newProps)
-        } else {
-            DirectVolume2d.updateValues(renderObject.values as DirectVolume2dValues, newProps)
-        }
+        DirectVolume.updateValues(renderObject.values, newProps)
         updateRenderableState(renderObject.state, newProps)
 
         currentProps = newProps

+ 6 - 11
src/mol-gl/render-object.ts

@@ -9,7 +9,7 @@ import { RenderableValues } from './renderable/schema';
 import { idFactory } from 'mol-util/id-factory';
 import { Context } from './webgl/context';
 import { GaussianDensityValues, GaussianDensityRenderable } from './renderable/gaussian-density';
-import { DirectVolume2dValues, DirectVolume2dRenderable, DirectVolume3dValues, DirectVolume3dRenderable } from './renderable/direct-volume';
+import { DirectVolumeValues, DirectVolumeRenderable } from './renderable/direct-volume';
 
 const getNextId = idFactory(0, 0x7FFFFFFF)
 
@@ -18,10 +18,9 @@ export interface MeshRenderObject extends BaseRenderObject { type: 'mesh', value
 export interface PointsRenderObject extends BaseRenderObject { type: 'points', values: PointsValues }
 export interface LinesRenderObject extends BaseRenderObject { type: 'lines', values: LinesValues }
 export interface GaussianDensityRenderObject extends BaseRenderObject { type: 'gaussian-density', values: GaussianDensityValues }
-export interface DirectVolume2dRenderObject extends BaseRenderObject { type: 'direct-volume-2d', values: DirectVolume2dValues }
-export interface DirectVolume3dRenderObject extends BaseRenderObject { type: 'direct-volume-3d', values: DirectVolume3dValues }
+export interface DirectVolumeRenderObject extends BaseRenderObject { type: 'direct-volume', values: DirectVolumeValues }
 
-export type RenderObject = MeshRenderObject | PointsRenderObject | LinesRenderObject | GaussianDensityRenderObject | DirectVolume2dRenderObject | DirectVolume3dRenderObject
+export type RenderObject = MeshRenderObject | PointsRenderObject | LinesRenderObject | GaussianDensityRenderObject | DirectVolumeRenderObject
 
 //
 
@@ -37,11 +36,8 @@ export function createLinesRenderObject(values: LinesValues, state: RenderableSt
 export function createGaussianDensityRenderObject(values: GaussianDensityValues, state: RenderableState): GaussianDensityRenderObject {
     return { id: getNextId(), type: 'gaussian-density', values, state }
 }
-export function createDirectVolume2dRenderObject(values: DirectVolume2dValues, state: RenderableState): DirectVolume2dRenderObject {
-    return { id: getNextId(), type: 'direct-volume-2d', values, state }
-}
-export function createDirectVolume3dRenderObject(values: DirectVolume3dValues, state: RenderableState): DirectVolume3dRenderObject {
-    return { id: getNextId(), type: 'direct-volume-3d', values, state }
+export function createDirectVolumeRenderObject(values: DirectVolumeValues, state: RenderableState): DirectVolumeRenderObject {
+    return { id: getNextId(), type: 'direct-volume', values, state }
 }
 
 export function createRenderable(ctx: Context, o: RenderObject): Renderable<any> {
@@ -50,7 +46,6 @@ export function createRenderable(ctx: Context, o: RenderObject): Renderable<any>
         case 'points': return PointsRenderable(ctx, o.id, o.values, o.state)
         case 'lines': return LinesRenderable(ctx, o.id, o.values, o.state)
         case 'gaussian-density': return GaussianDensityRenderable(ctx, o.id, o.values, o.state)
-        case 'direct-volume-2d': return DirectVolume2dRenderable(ctx, o.id, o.values, o.state)
-        case 'direct-volume-3d': return DirectVolume3dRenderable(ctx, o.id, o.values, o.state)
+        case 'direct-volume': return DirectVolumeRenderable(ctx, o.id, o.values, o.state)
     }
 }

+ 11 - 41
src/mol-gl/renderable/direct-volume.ts

@@ -11,7 +11,7 @@ import { AttributeSpec, Values, UniformSpec, GlobalUniformSchema, InternalSchema
 import { DirectVolumeShaderCode } from '../shader-code';
 import { ValueCell } from 'mol-util';
 
-export const DirectVolumeBaseSchema = {
+export const DirectVolumeSchema = {
     aColor: AttributeSpec('float32', 3, 0), // TODO not used, just for type checking
     uColor: UniformSpec('v3'),
     uColorTexDim: UniformSpec('v2'),
@@ -45,54 +45,24 @@ export const DirectVolumeBaseSchema = {
     uGridDim: UniformSpec('v3'),
     dRenderMode: DefineSpec('string', ['isosurface', 'volume']),
     tTransferTex: TextureSpec('image-uint8', 'rgba', 'ubyte', 'linear'),
+
+    dGridTexType: DefineSpec('string', ['2d', '3d']),
+    uGridTexDim: UniformSpec('v3'),
+    tGridTex: TextureSpec('texture', 'rgba', 'ubyte', 'linear'),
 }
-export type DirectVolumeBaseSchema = typeof DirectVolumeBaseSchema
-export type DirectVolumeBaseValues = Values<DirectVolumeBaseSchema>
+export type DirectVolumeSchema = typeof DirectVolumeSchema
+export type DirectVolumeValues = Values<DirectVolumeSchema>
 
-function getInternalValues(ctx: Context, id: number): InternalValues {
-    return {
+export function DirectVolumeRenderable(ctx: Context, id: number, values: DirectVolumeValues, state: RenderableState): Renderable<DirectVolumeValues> {
+    const schema = { ...GlobalUniformSchema, ...InternalSchema, ...DirectVolumeSchema }
+    const internalValues: InternalValues = {
         uObjectId: ValueCell.create(id)
     }
-}
-
-function DirectVolumeRenderable<T extends DirectVolumeBaseValues, S extends DirectVolumeBaseSchema>(ctx: Context, id: number, values: T, state: RenderableState, schema: S): Renderable<T> {
-    const fullSchema = Object.assign({}, GlobalUniformSchema, InternalSchema, schema)
-    const internalValues = getInternalValues(ctx, id)
-    const fullValues = Object.assign({}, values, internalValues)
     const shaderCode = DirectVolumeShaderCode
-    const renderItem = createRenderItem(ctx, 'triangles', shaderCode, fullSchema, fullValues)
+    const renderItem = createRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues })
     const renderable = createRenderable(renderItem, values, state);
 
     Object.defineProperty(renderable, 'opaque', { get: () => false });
 
     return renderable
-}
-
-// via 2d texture
-
-export const DirectVolume2dSchema = {
-    ...DirectVolumeBaseSchema,
-    dGridTexType: DefineSpec('string', ['2d']),
-    uGridTexDim: UniformSpec('v2'),
-    tGridTex: TextureSpec('texture2d', 'rgba', 'ubyte', 'linear'),
-}
-export type DirectVolume2dSchema = typeof DirectVolume2dSchema
-export type DirectVolume2dValues = Values<DirectVolume2dSchema>
-
-export function DirectVolume2dRenderable(ctx: Context, id: number, values: DirectVolume2dValues, state: RenderableState): Renderable<DirectVolume2dValues> {
-    return DirectVolumeRenderable(ctx, id, values, state, DirectVolume2dSchema)
-}
-
-// via 3d texture
-
-export const DirectVolume3dSchema = {
-    ...DirectVolumeBaseSchema,
-    dGridTexType: DefineSpec('string', ['3d']),
-    tGridTex: TextureSpec('texture3d', 'rgba', 'ubyte', 'linear'),
-}
-export type DirectVolume3dSchema = typeof DirectVolume3dSchema
-export type DirectVolume3dValues = Values<DirectVolume3dSchema>
-
-export function DirectVolume3dRenderable(ctx: Context, id: number, values: DirectVolume3dValues, state: RenderableState): Renderable<DirectVolume3dValues> {
-    return DirectVolumeRenderable(ctx, id, values, state, DirectVolume3dSchema)
 }

+ 2 - 2
src/mol-gl/renderable/gaussian-density.ts

@@ -25,9 +25,9 @@ export const GaussianDensitySchema = {
     uBboxMax: UniformSpec('v3'),
     uBboxSize: UniformSpec('v3'),
     uGridDim: UniformSpec('v3'),
-    uGridTexDim: UniformSpec('v2'),
+    uGridTexDim: UniformSpec('v3'),
     uAlpha: UniformSpec('f'),
-    tMinDistanceTex: TextureSpec('texture3d', 'rgba', 'ubyte', 'nearest'),
+    tMinDistanceTex: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
 
     dGridTexType: DefineSpec('string', ['2d', '3d']),
     dCalcType: DefineSpec('string', ['density', 'minDistance', 'groupId']),

+ 1 - 0
src/mol-gl/renderable/schema.ts

@@ -43,6 +43,7 @@ export type KindValue = {
     'image-float32': TextureImage<Float32Array>
     'volume-uint8': TextureVolume<Uint8Array>
     'volume-float32': TextureVolume<Float32Array>
+    'texture': Texture
     'texture2d': Texture
     'texture3d': Texture
 

+ 3 - 3
src/mol-gl/shader/direct-volume.frag

@@ -29,7 +29,7 @@ uniform sampler2D tMarker;
 #if defined(dGridTexType_2d)
     precision mediump sampler2D;
     uniform sampler2D tGridTex;
-    uniform vec2 uGridTexDim;
+    uniform vec3 uGridTexDim;
 #elif defined(dGridTexType_3d)
     precision mediump sampler3D;
     uniform sampler3D tGridTex;
@@ -64,11 +64,11 @@ const float albedo = 0.95;
 
 #if defined(dGridTexType_2d)
     vec4 textureVal(vec3 pos) {
-        return texture3dFrom2dLinear(tGridTex, pos, uGridDim, uGridTexDim);
+        return texture3dFrom2dLinear(tGridTex, pos, uGridDim, uGridTexDim.xy);
     }
     vec4 textureGroup(vec3 pos) {
         vec3 nearestPos = floor(pos * uGridDim + 0.5) / uGridDim + 0.5 / uGridDim;
-        return texture3dFrom2dNearest(tGridTex, nearestPos, uGridDim, uGridTexDim);
+        return texture3dFrom2dNearest(tGridTex, nearestPos, uGridDim, uGridTexDim.xy);
     }
 #elif defined(dGridTexType_3d)
     vec4 textureVal(vec3 pos) {

+ 2 - 2
src/mol-gl/shader/gaussian-density.frag

@@ -13,7 +13,7 @@ varying float vRadius;
     #if defined(dGridTexType_2d)
         precision mediump sampler2D;
         uniform sampler2D tMinDistanceTex;
-        uniform vec2 uGridTexDim;
+        uniform vec3 uGridTexDim;
     #elif defined(dGridTexType_3d)
         precision highp sampler3D;
         uniform sampler3D tMinDistanceTex;
@@ -36,7 +36,7 @@ uniform float uAlpha;
 #if defined(dCalcType_groupId)
     #if defined(dGridTexType_2d)
         vec4 textureMinDist(vec3 pos) {
-            return texture3dFrom2dNearest(tMinDistanceTex, pos, uGridDim, uGridTexDim);
+            return texture3dFrom2dNearest(tMinDistanceTex, pos, uGridDim, uGridTexDim.xy);
         }
     #elif defined(dGridTexType_3d)
         vec4 textureMinDist(vec3 pos) {

+ 4 - 4
src/mol-gl/webgl/render-item.ts

@@ -227,8 +227,8 @@ export function createRenderItem(ctx: Context, drawMode: DrawMode, shaderCode: S
             Object.keys(textureValues).forEach(k => {
                 const value = textureValues[k]
                 if (value.ref.version !== versions[k]) {
-                    // update of textures with kind 'texture2d' or 'texture3d' is done externally
-                    if (schema[k].kind !== 'texture2d' && schema[k].kind !== 'texture3d') {
+                    // update of textures with kind 'texture' is done externally
+                    if (schema[k].kind !== 'texture') {
                         // console.log('texture version changed, uploading image', k)
                         textures[k].load(value.ref.value as TextureImage<any> | TextureVolume<any>)
                         versions[k] = value.ref.version
@@ -246,8 +246,8 @@ export function createRenderItem(ctx: Context, drawMode: DrawMode, shaderCode: S
                     deleteVertexArray(ctx, vertexArrays[k])
                 })
                 Object.keys(textures).forEach(k => {
-                    // lifetime of textures with kind 'texture2d' or 'texture3d' is defined externally
-                    if (schema[k].kind !== 'texture2d' && schema[k].kind !== 'texture3d') {
+                    // lifetime of textures with kind 'texture' is defined externally
+                    if (schema[k].kind !== 'texture') {
                         textures[k].destroy()
                     }
                 })

+ 2 - 5
src/mol-gl/webgl/texture.ts

@@ -19,8 +19,7 @@ export type TextureKindValue = {
     'image-float32': TextureImage<Float32Array>
     'volume-uint8': TextureVolume<Uint8Array>
     'volume-float32': TextureVolume<Float32Array>
-    'texture2d': Texture
-    'texture3d': Texture
+    'texture': Texture
 }
 export type TextureValueType = Helpers.ValueOf<TextureKindValue>
 export type TextureKind = keyof TextureKindValue
@@ -35,13 +34,11 @@ export function getTarget(ctx: Context, kind: TextureKind): number {
     switch (kind) {
         case 'image-uint8': return gl.TEXTURE_2D
         case 'image-float32': return gl.TEXTURE_2D
-        case 'texture2d': return gl.TEXTURE_2D
     }
     if (isWebGL2(gl)) {
         switch (kind) {
             case 'volume-uint8': return gl.TEXTURE_3D
             case 'volume-float32': return gl.TEXTURE_3D
-            case 'texture3d': return gl.TEXTURE_3D
         }
     }
     throw new Error('unknown texture kind')
@@ -252,7 +249,7 @@ export function createTextures(ctx: Context, schema: RenderableSchema, values: T
     Object.keys(schema).forEach((k, i) => {
         const spec = schema[k]
         if (spec.type === 'texture') {
-            if (spec.kind === 'texture2d' || spec.kind === 'texture3d') {
+            if (spec.kind === 'texture') {
                 textures[k] = values[k].ref.value as Texture
             } else {
                 const texture = createTexture(ctx, spec.kind, spec.format, spec.dataType, spec.filter)

+ 2 - 2
src/mol-math/geometry/gaussian-density/gpu.ts

@@ -10,7 +10,7 @@ import { PositionData, DensityData, DensityTextureData } from '../common'
 import { Box3D } from '../../geometry'
 import { GaussianDensityProps, getDelta } from '../gaussian-density'
 import { OrderedSet } from 'mol-data/int'
-import { Vec3, Tensor, Mat4, Vec2 } from '../../linear-algebra'
+import { Vec3, Tensor, Mat4 } from '../../linear-algebra'
 import { GaussianDensityValues } from 'mol-gl/renderable/gaussian-density'
 import { ValueCell, defaults } from 'mol-util'
 import { RenderableState, Renderable } from 'mol-gl/renderable'
@@ -241,7 +241,7 @@ function getGaussianDensityRenderObject(webgl: Context, drawCount: number, posit
         uBboxMax: ValueCell.create(box.max),
         uBboxSize: ValueCell.create(extent),
         uGridDim: ValueCell.create(dimensions),
-        uGridTexDim: ValueCell.create(Vec2.create(texDimX, texDimY)),
+        uGridTexDim: ValueCell.create(Vec3.create(texDimX, texDimY, 0)),
         uAlpha: ValueCell.create(smoothness),
         tMinDistanceTex: ValueCell.create(minDistanceTexture),