diff --git a/src/apps/canvas/structure-view.ts b/src/apps/canvas/structure-view.ts index d13cae50b250b4e2fb848589bb89f14efbce3030..3b4658514a82a258c73edc8f7f15dacfef6b3dd1 100644 --- a/src/apps/canvas/structure-view.ts +++ b/src/apps/canvas/structure-view.ts @@ -211,7 +211,8 @@ export async function StructureView(app: App, viewer: Viewer, models: ReadonlyAr console.log('createStructureRepr') for (const k in structureRepresentations) { if (active[k]) { - await app.runTask(structureRepresentations[k].createOrUpdate({}, structure).run( + const p = { webgl: viewer.webgl } + await app.runTask(structureRepresentations[k].createOrUpdate(p, structure).run( progress => console.log(Progress.format(progress)) ), 'Create/update representation') viewer.add(structureRepresentations[k]) diff --git a/src/apps/canvas/volume-view.ts b/src/apps/canvas/volume-view.ts index 422934fdf4e1db5ee695d3d1524f869027a823cb..1ef40f6dda5e97284b971906a8fa556215f64976 100644 --- a/src/apps/canvas/volume-view.ts +++ b/src/apps/canvas/volume-view.ts @@ -55,7 +55,8 @@ export async function VolumeView(app: App, viewer: Viewer, volume: VolumeData, p async function createVolumeRepr() { for (const k in volumeRepresentations) { if (active[k]) { - await app.runTask(volumeRepresentations[k].createOrUpdate({}, volume).run( + const p = { webgl: viewer.webgl } + await app.runTask(volumeRepresentations[k].createOrUpdate(p, volume).run( progress => console.log(Progress.format(progress)) ), 'Create/update representation') viewer.add(volumeRepresentations[k]) diff --git a/src/mol-geo/geometry/geometry.ts b/src/mol-geo/geometry/geometry.ts index 7a3879effdba26117a00537759c8df5f32a88633..4ad88a210ae595fe25cffbc0185c100307eba054 100644 --- a/src/mol-geo/geometry/geometry.ts +++ b/src/mol-geo/geometry/geometry.ts @@ -15,9 +15,11 @@ import { LocationIterator } from '../util/location-iterator'; import { ColorType } from './color-data'; import { SizeType } from './size-data'; import { Lines } from './lines/lines'; -import { paramDefaultValues, RangeParam, BooleanParam, SelectParam, ColorParam, StructureParam } from 'mol-view/parameter' +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 { GLRenderingContext } from 'mol-gl/webgl/compat'; +import { Context } from 'mol-gl/webgl/context'; // @@ -70,6 +72,7 @@ export namespace Geometry { colorTheme: SelectParam<ColorThemeName>('Color Theme', '', 'uniform', ColorThemeOptions), colorValue: ColorParam('Color Value', '', Color(0xCCCCCC)), structure: StructureParam('Structure', '', Structure.Empty), + webgl: ValueParam('WebGL Context', '', undefined as Context | undefined), } export const DefaultProps = paramDefaultValues(Params) export type Props = typeof DefaultProps diff --git a/src/mol-geo/representation/structure/units-visual.ts b/src/mol-geo/representation/structure/units-visual.ts index 76c2dac24bbd51f8249216f12fc98493214b8a0b..d645473bf2e40edd3f9bda9c4d1a69a5fcbab21d 100644 --- a/src/mol-geo/representation/structure/units-visual.ts +++ b/src/mol-geo/representation/structure/units-visual.ts @@ -541,6 +541,9 @@ export function UnitsDirectVolumeVisual<P extends UnitsDirectVolumeProps>(builde let currentConformationId: UUID async function create(ctx: RuntimeContext, group: Unit.SymmetryGroup, props: Partial<P> = {}) { + const { webgl } = props + if (webgl === undefined) throw new Error('UnitsDirectVolumeVisual requires `webgl` in props') + currentProps = Object.assign({}, defaultProps, props, { structure: currentStructure }) currentGroup = group @@ -550,12 +553,17 @@ export function UnitsDirectVolumeVisual<P extends UnitsDirectVolumeProps>(builde ? await createGeometry(ctx, unit, currentStructure, currentProps, directVolume) : DirectVolume2d.createEmpty(directVolume) + console.log('directVolume', directVolume) + // TODO create empty location iterator when not in unitKinds locationIt = createLocationIterator(group) renderObject = await createUnitsDirectVolumeRenderObject(ctx, group, directVolume, locationIt, currentProps) } async function update(ctx: RuntimeContext, props: Partial<P> = {}) { + const { webgl } = props + if (webgl === undefined) throw new Error('UnitsDirectVolumeVisual requires `webgl` in props') + if (!renderObject) return const newProps = Object.assign({}, currentProps, props, { structure: currentStructure }) diff --git a/src/mol-geo/representation/structure/visual/gaussian-density-volume.ts b/src/mol-geo/representation/structure/visual/gaussian-density-volume.ts index 1fba2acf8fadff4e3c687312ac71833c251f0ae2..83a90531ac83012082919676ef3c96cbf39ec75a 100644 --- a/src/mol-geo/representation/structure/visual/gaussian-density-volume.ts +++ b/src/mol-geo/representation/structure/visual/gaussian-density-volume.ts @@ -17,8 +17,8 @@ import { Vec3, Vec2 } from 'mol-math/linear-algebra'; async function createGaussianDensityVolume(ctx: RuntimeContext, unit: Unit, structure: Structure, props: GaussianDensityProps, directVolume?: DirectVolume2d): Promise<DirectVolume2d> { const p = { ...props, useGpu: true, ignoreCache: true } - const { transform, renderTarget, bbox, gridDimension } = await unit.computeGaussianDensity(p, ctx) - if (!renderTarget || !bbox || !gridDimension) throw new Error('missing renderTarget and/or boundingBox and/or gridDimension') + const { transform, texture, bbox, gridDimension } = await unit.computeGaussianDensity(p, ctx) + if (!texture || !bbox || !gridDimension) throw new Error('missing renderTarget and/or boundingBox and/or gridDimension') if (directVolume) { ValueCell.update(directVolume.gridDimension, gridDimension) diff --git a/src/mol-geo/representation/volume/direct-volume.ts b/src/mol-geo/representation/volume/direct-volume.ts index 8574b8671b8150f6c636a76929a20f3307b540ab..8c1aea142c9feabd0585df879609b526cf5c1dc7 100644 --- a/src/mol-geo/representation/volume/direct-volume.ts +++ b/src/mol-geo/representation/volume/direct-volume.ts @@ -17,13 +17,13 @@ import { ValueCell } from 'mol-util'; import { DirectVolume2d, DirectVolume3d } from '../../geometry/direct-volume/direct-volume'; import { Vec2, Vec3 } from 'mol-math/linear-algebra'; import { Box3D } from 'mol-math/geometry'; -import { createImageData } from 'mol-gl/webgl/context'; +import { createImageData, Context } from 'mol-gl/webgl/context'; import { debugTexture } from 'mol-gl/util'; import { DirectVolume3dValues, DirectVolume2dValues } from 'mol-gl/renderable/direct-volume'; // 2d volume texture -function getVolumeTexture2dLayout(dim: Vec3, maxTextureSize = 4096) { +function getVolumeTexture2dLayout(dim: Vec3, maxTextureSize: number) { let width = 0 let height = dim[1] let rows = 1 @@ -41,19 +41,19 @@ function getVolumeTexture2dLayout(dim: Vec3, maxTextureSize = 4096) { return { width, height, columns, rows } } -function createVolumeTexture2d(volume: VolumeData) { +function createVolumeTexture2d(volume: VolumeData, maxTextureSize: number) { const { data: tensor, dataStats: stats } = volume const { space, data } = tensor const dim = space.dimensions as Vec3 const { get } = space - const { width, height, columns, rows } = getVolumeTexture2dLayout(dim) + const { width, height, columns, rows } = getVolumeTexture2dLayout(dim, maxTextureSize) const array = new Uint8Array(width * height * 4) const textureImage = { array, width, height } const [ xl, yl, zl ] = dim - const xlp = xl + 1 - const ylp = yl + 1 + const xlp = xl + 1 // horizontal padding + const ylp = yl + 1 // vertical padding function setTex(value: number, x: number, y: number, z: number) { const column = Math.floor(((z * xlp) % width) / xlp) @@ -77,10 +77,9 @@ function createVolumeTexture2d(volume: VolumeData) { return textureImage } -export function createDirectVolume2d(ctx: RuntimeContext, volume: VolumeData, directVolume?: DirectVolume2d) { +export function createDirectVolume2d(ctx: RuntimeContext, webgl: Context, volume: VolumeData, directVolume?: DirectVolume2d) { const gridDimension = volume.data.space.dimensions as Vec3 - // const textureImage = createTextureImage(1, 4) - const textureImage = createVolumeTexture2d(volume) + const textureImage = createVolumeTexture2d(volume, webgl.maxTextureSize) const transform = VolumeData.getGridToCartesianTransform(volume) console.log('textureImage', textureImage) @@ -90,7 +89,9 @@ export function createDirectVolume2d(ctx: RuntimeContext, volume: VolumeData, di Box3D.add(bbox, gridDimension) Box3D.transform(bbox, bbox, transform) - const dim = Vec3.create(gridDimension[0] + 1, gridDimension[1] + 1, gridDimension[2]) + const dim = Vec3.create(gridDimension[0], gridDimension[1], gridDimension[2]) + dim[0] += 1 // horizontal padding + dim[0] += 1 // vertical padding if (directVolume) { ValueCell.update(directVolume.gridDimension, dim) @@ -135,8 +136,7 @@ function createVolumeTexture3d(volume: VolumeData) { let i = 0 for (let z = 0; z < depth; ++z) { for (let y = 0; y < height; ++y) { - for (let x = 0; x < width; ++x) { - + for (let x = 0; x < width; ++x) { array[i + 3] = ((get(data, x, y, z) - stats.min) / (stats.max - stats.min)) * 255 i += 4 } @@ -146,7 +146,7 @@ function createVolumeTexture3d(volume: VolumeData) { return textureVolume } -export function createDirectVolume3d(ctx: RuntimeContext, volume: VolumeData, directVolume?: DirectVolume3d) { +export function createDirectVolume3d(ctx: RuntimeContext, webgl: Context, volume: VolumeData, directVolume?: DirectVolume3d) { const gridDimension = volume.data.space.dimensions as Vec3 const textureVolume = createVolumeTexture3d(volume) const transform = VolumeData.getGridToCartesianTransform(volume) @@ -181,10 +181,6 @@ export function createDirectVolume3d(ctx: RuntimeContext, volume: VolumeData, di // -function hasWebGL2() { - return true -} - export const DirectVolumeParams = { ...Geometry.Params, ...DirectVolume2d.Params @@ -199,6 +195,9 @@ export function DirectVolumeVisual(): VolumeVisual<DirectVolumeProps> { let directVolume: DirectVolume2d | DirectVolume3d async function create(ctx: RuntimeContext, volume: VolumeData, props: Partial<DirectVolumeProps> = {}) { + const { webgl } = props + if (webgl === undefined) throw new Error('DirectVolumeVisual requires `webgl` in props') + currentProps = { ...DefaultDirectVolumeProps, ...props } if (props.isoValueRelative) { // currentProps.isoValueAbsolute = VolumeIsoValue.calcAbsolute(currentVolume.dataStats, props.isoValueRelative) @@ -206,26 +205,28 @@ export function DirectVolumeVisual(): VolumeVisual<DirectVolumeProps> { const state = createRenderableState(currentProps) - if (hasWebGL2()) { - console.log('createing 3d volume') - directVolume = await createDirectVolume3d(ctx, volume, directVolume as DirectVolume3d) + 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, currentProps) renderObject = createDirectVolume3dRenderObject(values, state) } else { - directVolume = await createDirectVolume2d(ctx, volume, directVolume as DirectVolume2d) + directVolume = await createDirectVolume2d(ctx, webgl, volume, directVolume as DirectVolume2d) const values = await DirectVolume2d.createValues(ctx, directVolume as DirectVolume2d, currentProps) renderObject = createDirectVolume2dRenderObject(values, state) } } async function update(ctx: RuntimeContext, props: Partial<DirectVolumeProps> = {}) { - console.log('props', props) + const { webgl } = props + if (webgl === undefined) throw new Error('DirectVolumeVisual requires `webgl` in props') + const newProps = { ...currentProps, ...props } if (props.isoValueRelative) { // newProps.isoValueAbsolute = VolumeIsoValue.calcAbsolute(currentVolume.dataStats, props.isoValueRelative) } - if (hasWebGL2()) { + if (webgl.isWebGL2) { DirectVolume3d.updateValues(renderObject.values as DirectVolume3dValues, newProps) } else { DirectVolume2d.updateValues(renderObject.values as DirectVolume2dValues, newProps) diff --git a/src/mol-math/geometry/common.ts b/src/mol-math/geometry/common.ts index ccb246258fcab53b4a4deabb433a9c2728749124..e7d730768f119e4aee5890536b8793ec56cd98e2 100644 --- a/src/mol-math/geometry/common.ts +++ b/src/mol-math/geometry/common.ts @@ -7,8 +7,8 @@ import { OrderedSet } from 'mol-data/int' import { Mat4, Tensor, Vec3 } from '../linear-algebra'; -import { RenderTarget } from 'mol-gl/webgl/render-target'; import { Box3D } from '../geometry'; +import { Texture } from 'mol-gl/webgl/texture'; export interface PositionData { x: ArrayLike<number>, @@ -25,7 +25,7 @@ export type DensityData = { field: Tensor, idField: Tensor, - renderTarget?: RenderTarget, + texture?: Texture, bbox?: Box3D, gridDimension?: Vec3 } \ No newline at end of file diff --git a/src/mol-math/geometry/gaussian-density/gpu.ts b/src/mol-math/geometry/gaussian-density/gpu.ts index 89092bc821b171958b1c0b8b22c6af653ff22778..0d42cc35c71367237b834c1890380571b14181be 100644 --- a/src/mol-math/geometry/gaussian-density/gpu.ts +++ b/src/mol-math/geometry/gaussian-density/gpu.ts @@ -15,7 +15,6 @@ import { GaussianDensityValues } from 'mol-gl/renderable/gaussian-density' import { ValueCell } from 'mol-util' import { RenderableState } from 'mol-gl/renderable' import { createRenderable, createGaussianDensityRenderObject } from 'mol-gl/render-object' -import { createRenderTarget } from 'mol-gl/webgl/render-target' import { Context, createContext, getGLContext } from 'mol-gl/webgl/context'; import { createFramebuffer } from 'mol-gl/webgl/framebuffer'; import { createTexture, Texture, TextureAttachment } from 'mol-gl/webgl/texture'; @@ -26,6 +25,7 @@ export async function GaussianDensityGPU(ctx: RuntimeContext, position: Position const webgl = getWebGLContext() const useMultiDraw = webgl.maxDrawBuffers > 0 + console.log('useMultiDraw', useMultiDraw) console.time('gpu gaussian density render') const { texture, scale, bbox, dim } = useMultiDraw ? @@ -46,9 +46,7 @@ export async function GaussianDensityGPU(ctx: RuntimeContext, position: Position Mat4.fromScaling(transform, scale) Mat4.setTranslation(transform, bbox.min) - const renderTarget = createRenderTarget(webgl, dim[0], dim[1]) - - return { field, idField, transform, renderTarget, bbox, gridDimension: dim } + return { field, idField, transform, texture, bbox, gridDimension: dim } } // diff --git a/src/mol-view/parameter.ts b/src/mol-view/parameter.ts index eec8b7a9c08d9503ec60741b16b714a24c752620..2110b3db36ba6eab84764a4210e1e88e636b4667 100644 --- a/src/mol-view/parameter.ts +++ b/src/mol-view/parameter.ts @@ -13,6 +13,13 @@ export interface BaseParam<T> { defaultValue: T } +export interface ValueParam<T> extends BaseParam<T> { + type: 'value' +} +export function ValueParam<T>(label: string, description: string, defaultValue: T): ValueParam<T> { + return { type: 'value', label, description, defaultValue } +} + export interface SelectParam<T extends string> extends BaseParam<T> { type: 'select' /** array of (value, label) tupels */ @@ -81,7 +88,7 @@ export function StructureParam(label: string, description: string, defaultValue: return { type: 'structure', label, description, defaultValue } } -export type Param = SelectParam<any> | MultiSelectParam<any> | BooleanParam | RangeParam | TextParam | ColorParam | NumberParam | StructureParam +export type Param = ValueParam<any> | SelectParam<any> | MultiSelectParam<any> | BooleanParam | RangeParam | TextParam | ColorParam | NumberParam | StructureParam export type Params = { [k: string]: Param } diff --git a/src/mol-view/viewer.ts b/src/mol-view/viewer.ts index 91a42cdacca0dd60d7cf26622b78c9af09c60e0c..7d092a8370f2cd7520dad135573b5a99713dc140 100644 --- a/src/mol-view/viewer.ts +++ b/src/mol-view/viewer.ts @@ -16,7 +16,7 @@ import TrackballControls from './controls/trackball' import { Viewport } from './camera/util' import { PerspectiveCamera } from './camera/perspective' import { resizeCanvas } from './util'; -import { createContext, getGLContext } from 'mol-gl/webgl/context'; +import { createContext, getGLContext, Context } from 'mol-gl/webgl/context'; import { Representation } from 'mol-geo/representation'; import { createRenderTarget } from 'mol-gl/webgl/render-target'; import Scene from 'mol-gl/scene'; @@ -27,6 +27,8 @@ import { Loci, EmptyLoci, isEmptyLoci } from 'mol-model/loci'; import { Color } from 'mol-util/color'; interface Viewer { + webgl: Context, + center: (p: Vec3) => void hide: (repr: Representation<any>) => void @@ -247,6 +249,8 @@ namespace Viewer { handleResize() return { + webgl: ctx, + center: (p: Vec3) => { Vec3.set(controls.target, p[0], p[1], p[2]) },