diff --git a/src/mol-geo/representation/structure/visual/gaussian-density-point.ts b/src/mol-geo/representation/structure/visual/gaussian-density-point.ts index ed7254ae3adebbe7fcb8eeade9bdfe3af2bfbfdb..9a26d96019acfd67fbfe01967205328cf3bc0fc1 100644 --- a/src/mol-geo/representation/structure/visual/gaussian-density-point.ts +++ b/src/mol-geo/representation/structure/visual/gaussian-density-point.ts @@ -69,7 +69,6 @@ export function GaussianDensityPointVisual(): UnitsVisual<GaussianDensityPointPr if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true if (newProps.useGpu !== currentProps.useGpu) state.createGeometry = true - if (newProps.readSlices !== currentProps.readSlices) state.createGeometry = true if (newProps.ignoreCache !== currentProps.ignoreCache) state.createGeometry = true } }) 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 5f59467b42aaa9ae7c8a48e690a2402893795240..1fba2acf8fadff4e3c687312ac71833c251f0ae2 100644 --- a/src/mol-geo/representation/structure/visual/gaussian-density-volume.ts +++ b/src/mol-geo/representation/structure/visual/gaussian-density-volume.ts @@ -68,7 +68,6 @@ export function GaussianDensityVolumeVisual(): UnitsVisual<GaussianDensityVolume if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true if (newProps.useGpu !== currentProps.useGpu) state.createGeometry = true - if (newProps.readSlices !== currentProps.readSlices) state.createGeometry = true if (newProps.ignoreCache !== currentProps.ignoreCache) state.createGeometry = true } }) diff --git a/src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts b/src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts index 99ef1b785901dafffd99f7a3a953b1ac7963cb53..8036e70041e7c44d851850bfe2bf6c88e2f515b2 100644 --- a/src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts +++ b/src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts @@ -93,7 +93,6 @@ export function GaussianSurfaceVisual(): UnitsVisual<GaussianSurfaceProps> { if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true if (newProps.useGpu !== currentProps.useGpu) state.createGeometry = true - if (newProps.readSlices !== currentProps.readSlices) state.createGeometry = true if (newProps.ignoreCache !== currentProps.ignoreCache) state.createGeometry = true } }) diff --git a/src/mol-geo/representation/structure/visual/gaussian-surface-wireframe.ts b/src/mol-geo/representation/structure/visual/gaussian-surface-wireframe.ts index f14369d6f7aace9d77f1fd021d8d53fd4e0e25a9..3d1da6e79ce63dee34a04cda3b393b5d0c22fcf1 100644 --- a/src/mol-geo/representation/structure/visual/gaussian-surface-wireframe.ts +++ b/src/mol-geo/representation/structure/visual/gaussian-surface-wireframe.ts @@ -53,7 +53,6 @@ export function GaussianWireframeVisual(): UnitsVisual<GaussianWireframeProps> { if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true if (newProps.useGpu !== currentProps.useGpu) state.createGeometry = true - if (newProps.readSlices !== currentProps.readSlices) state.createGeometry = true if (newProps.ignoreCache !== currentProps.ignoreCache) state.createGeometry = true } }) diff --git a/src/mol-gl/webgl/texture.ts b/src/mol-gl/webgl/texture.ts index c105058d210950832d363b2a530e8215f07de35b..6d6e2447b586497d07db458eaef43f683b568c0c 100644 --- a/src/mol-gl/webgl/texture.ts +++ b/src/mol-gl/webgl/texture.ts @@ -114,7 +114,11 @@ export interface Texture { readonly internalFormat: number readonly type: number - define: (x: number, y: number, z: number) => void + readonly width: number + readonly height: number + readonly depth: number + + define: (width: number, height: number, depth?: number) => void load: (image: TextureImage<any>) => void bind: (id: TextureId) => void unbind: (id: TextureId) => void @@ -151,6 +155,8 @@ export function createTexture(ctx: Context, kind: TextureKind, _format: TextureF gl.texParameteri(target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.bindTexture(target, null) + let width = 0, height = 0, depth = 0 + let destroyed = false ctx.textureCount += 1 @@ -161,7 +167,12 @@ export function createTexture(ctx: Context, kind: TextureKind, _format: TextureF internalFormat, type, - define: (width: number, height: number, depth?: number) => { + get width () { return width }, + get height () { return height }, + get depth () { return depth }, + + define: (_width: number, _height: number, _depth?: number) => { + width = _width, height = _height, depth = _depth || 0 gl.bindTexture(target, texture) if (target === gl.TEXTURE_2D) { // TODO remove cast when webgl2 types are fixed @@ -178,11 +189,13 @@ export function createTexture(ctx: Context, kind: TextureKind, _format: TextureF gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1); gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE); if (target === gl.TEXTURE_2D) { - const { array, width, height } = data as TextureImage<any>; + const { array, width: _width, height: _height } = data as TextureImage<any> + width = _width, height = _height; // TODO remove cast when webgl2 types are fixed (gl as WebGLRenderingContext).texImage2D(target, 0, internalFormat, width, height, 0, format, type, array) } else if (target === (gl as WebGL2RenderingContext).TEXTURE_3D) { - const { array, width, height, depth } = data as TextureVolume<any>; + const { array, width: _width, height: _height, depth: _depth } = data as TextureVolume<any> + width = _width, height = _height, depth = _depth; (gl as WebGL2RenderingContext).texImage3D(target, 0, internalFormat, width, height, depth, 0, format, type, array) } else { throw new Error('unknown texture target') diff --git a/src/mol-math/geometry/gaussian-density.ts b/src/mol-math/geometry/gaussian-density.ts index 16577af6b9305216a661bd28cf7e917a9913d20d..cdc1f696f0095691cec96b72b21ccf3884aed0a5 100644 --- a/src/mol-math/geometry/gaussian-density.ts +++ b/src/mol-math/geometry/gaussian-density.ts @@ -19,7 +19,6 @@ export const DefaultGaussianDensityProps = { resolution: 1, radiusOffset: 0, smoothness: 1.5, - readSlices: false, useGpu: true, } export type GaussianDensityProps = typeof DefaultGaussianDensityProps diff --git a/src/mol-math/geometry/gaussian-density/gpu.ts b/src/mol-math/geometry/gaussian-density/gpu.ts index 5bcd606013c1ad240244f4f9d639dcaf46ff16a8..89092bc821b171958b1c0b8b22c6af653ff22778 100644 --- a/src/mol-math/geometry/gaussian-density/gpu.ts +++ b/src/mol-math/geometry/gaussian-density/gpu.ts @@ -21,143 +21,48 @@ import { createFramebuffer } from 'mol-gl/webgl/framebuffer'; import { createTexture, Texture, TextureAttachment } from 'mol-gl/webgl/texture'; import { GLRenderingContext } from 'mol-gl/webgl/compat'; -let webglContext: Context -function getWebGLContext() { - if (webglContext) return webglContext - const canvas = document.createElement('canvas') - const gl = getGLContext(canvas, { - alpha: true, - antialias: false, - depth: false, - preserveDrawingBuffer: true - }) - if (!gl) throw new Error('Could not create a WebGL rendering context') - webglContext = createContext(gl) - return webglContext -} - export async function GaussianDensityGPU(ctx: RuntimeContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps): Promise<DensityData> { // TODO allow passing a context via props const webgl = getWebGLContext() - if (webgl.maxDrawBuffers > 0) { - console.log('GaussianDensityMultiDrawBuffer') - const { texture, scale, bbox, dim } = await GaussianDensityMultiDrawBuffer(ctx, webgl, position, box, radius, props) - - console.time('gpu gaussian density 3d texture read') - const field = fieldFromTexture3d(webgl, texture, dim) - console.timeEnd('gpu gaussian density 3d texture read') - - const idData = field.space.create() - const idField = Tensor.create(field.space, idData) - - const transform = Mat4.identity() - 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 } - } else { - console.log('GaussianDensitySingleDrawBuffer') - return GaussianDensitySingleDrawBuffer(ctx, webgl, position, box, radius, props) - } -} - -async function prepareGaussianDensityData(ctx: RuntimeContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps) { - const { resolution, radiusOffset } = props - - const { indices, x, y, z } = position - const n = OrderedSet.size(indices) - - const positions = new Float32Array(n * 3) - const radii = new Float32Array(n) - - let maxRadius = 0 - - for (let i = 0; i < n; ++i) { - const j = OrderedSet.getAt(indices, i); - - positions[i * 3] = x[j] - positions[i * 3 + 1] = y[j] - positions[i * 3 + 2] = z[j] - const r = radius(j) + radiusOffset - if (maxRadius < r) maxRadius = r - radii[i] = r - - if (i % 10000 === 0 && ctx.shouldUpdate) { - await ctx.update({ message: 'preparing density data', current: i, max: n }) - } - } - - - const pad = maxRadius * 2 + resolution - const expandedBox = Box3D.expand(Box3D.empty(), box, Vec3.create(pad, pad, pad)); - const extent = Vec3.sub(Vec3.zero(), expandedBox.max, expandedBox.min) - - const delta = getDelta(expandedBox, resolution) - const dim = Vec3.zero() - Vec3.ceil(dim, Vec3.mul(dim, extent, delta)) - console.log('grid dim gpu', dim) - - return { drawCount: n, positions, radii, delta, expandedBox, dim } -} - -function getGaussianDensityRenderObject(webgl: Context, drawCount: number, positions: Float32Array, radii: Float32Array, box: Box3D, dimensions: Vec3, smoothness: number) { - const extent = Vec3.sub(Vec3.zero(), box.max, box.min) - - const values: GaussianDensityValues = { - drawCount: ValueCell.create(drawCount), - instanceCount: ValueCell.create(1), - - aRadius: ValueCell.create(radii), - aPosition: ValueCell.create(positions), - - uCurrentSlice: ValueCell.create(0), - uCurrentX: ValueCell.create(0), - uCurrentY: ValueCell.create(0), - uBboxMin: ValueCell.create(box.min), - uBboxMax: ValueCell.create(box.max), - uBboxSize: ValueCell.create(extent), - uGridDim: ValueCell.create(dimensions), - uAlpha: ValueCell.create(smoothness), + const useMultiDraw = webgl.maxDrawBuffers > 0 - dDrawBuffers: ValueCell.create(Math.min(8, webgl.maxDrawBuffers)), - } - const state: RenderableState = { - visible: true, - depthMask: false - } + console.time('gpu gaussian density render') + const { texture, scale, bbox, dim } = useMultiDraw ? + await GaussianDensityMultiDrawBuffer(ctx, webgl, position, box, radius, props) : + await GaussianDensitySingleDrawBuffer(ctx, webgl, position, box, radius, props) + console.timeEnd('gpu gaussian density render') - const renderObject = createGaussianDensityRenderObject(values, state) + console.time('gpu gaussian density read') + const field = useMultiDraw ? + fieldFromTexture3d(webgl, texture, dim) : + fieldFromTexture2d(webgl, texture, dim) + console.timeEnd('gpu gaussian density read') - return renderObject -} + const idData = field.space.create() + const idField = Tensor.create(field.space, idData) -// + const transform = Mat4.identity() + Mat4.fromScaling(transform, scale) + Mat4.setTranslation(transform, bbox.min) -function setRenderingDefaults(gl: GLRenderingContext) { - gl.disable(gl.CULL_FACE) - gl.frontFace(gl.CCW) - gl.cullFace(gl.BACK) + const renderTarget = createRenderTarget(webgl, dim[0], dim[1]) - gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) - gl.blendEquation(gl.FUNC_ADD) - gl.enable(gl.BLEND) + return { field, idField, transform, renderTarget, bbox, gridDimension: dim } } // -async function GaussianDensitySingleDrawBuffer(ctx: RuntimeContext, webgl: Context, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps): Promise<DensityData> { - const { readSlices, smoothness } = props +async function GaussianDensitySingleDrawBuffer(ctx: RuntimeContext, webgl: Context, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps) { + const { smoothness } = props const { drawCount, positions, radii, delta, expandedBox, dim } = await prepareGaussianDensityData(ctx, position, box, radius, props) + const [ dx, dy, dz ] = dim const renderObject = getGaussianDensityRenderObject(webgl, drawCount, positions, radii, expandedBox, dim, smoothness) const renderable = createRenderable(webgl, renderObject) // - // TODO fallback to lower resolution when texture size is not large enough const maxTexSize = webgl.maxTextureSize let fboTexDimX = 0 let fboTexDimY = dim[1] @@ -172,93 +77,43 @@ async function GaussianDensitySingleDrawBuffer(ctx: RuntimeContext, webgl: Conte fboTexDimX = dim[0] * dim[2] } - console.log('dim', dim, 'cols', fboTexCols, 'rows', fboTexRows) - - // - - const space = Tensor.Space(dim, [2, 1, 0], Float32Array) - const data = space.create() - const field = Tensor.create(space, data) - - const idData = space.create() - const idField = Tensor.create(space, idData) - // const { gl } = webgl const { uCurrentSlice, uCurrentX, uCurrentY } = renderObject.values - const program = renderable.getProgram('draw') - const renderTarget = createRenderTarget(webgl, fboTexDimX, fboTexDimY) + const framebuffer = createFramebuffer(webgl) + framebuffer.bind() + const texture = createTexture(webgl, 'image-uint8', 'rgba', 'ubyte', 'linear') + texture.define(fboTexDimX, fboTexDimY) + + const program = renderable.getProgram('draw') program.use() - renderTarget.bind() setRenderingDefaults(gl) + texture.attachFramebuffer(framebuffer, 0) - const slice = new Uint8Array(dim[0] * dim[1] * 4) - - console.time('gpu gaussian density slices') let currCol = 0 let currY = 0 let currX = 0 - let j = 0 - for (let i = 0; i < dim[2]; ++i) { + for (let i = 0; i < dz; ++i) { if (currCol >= fboTexCols) { currCol -= fboTexCols - currY += dim[1] + currY += dy currX = 0 } - gl.viewport(currX, currY, dim[0], dim[1]) + gl.viewport(currX, currY, dx, dy) ValueCell.update(uCurrentSlice, i) ValueCell.update(uCurrentX, currX) ValueCell.update(uCurrentY, currY) renderable.render('draw') - if (readSlices) { - renderTarget.readBuffer(currX, currY, dim[0], dim[1], slice) - for (let iy = 0; iy < dim[1]; ++iy) { - for (let ix = 0; ix < dim[0]; ++ix) { - data[j] = slice[4 * (iy * dim[0] + ix)] / 255 - ++j - } - } - } ++currCol - currX += dim[0] - } - console.timeEnd('gpu gaussian density slices') - - // - - if (!readSlices) { - console.time('gpu gaussian density full') - renderTarget.getBuffer() - const { array } = renderTarget.image - let idx = 0 - let tmpCol = 0 - let tmpRow = 0 - for (let iz = 0; iz < dim[2]; ++iz) { - if (tmpCol >= fboTexCols ) { - tmpCol = 0 - tmpRow += dim[1] - } - for (let iy = 0; iy < dim[1]; ++iy) { - for (let ix = 0; ix < dim[0]; ++ix) { - data[idx] = array[4 * (tmpCol * dim[0] + (iy + tmpRow) * fboTexDimX + ix)] / 255 - idx++ - } - } - tmpCol++ - } - console.timeEnd('gpu gaussian density full') + currX += dx } - // - - const transform = Mat4.identity() - Mat4.fromScaling(transform, Vec3.inverse(Vec3.zero(), delta)) - Mat4.setTranslation(transform, expandedBox.min) + framebuffer.destroy() // clean up - return { field, idField, transform, renderTarget, bbox: expandedBox, gridDimension: dim } + return { texture, scale: Vec3.inverse(Vec3.zero(), delta), bbox: expandedBox, dim } } async function GaussianDensityMultiDrawBuffer(ctx: RuntimeContext, webgl: Context, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps) { @@ -299,14 +154,12 @@ async function GaussianDensityMultiDrawBuffer(ctx: RuntimeContext, webgl: Contex gl.viewport(0, 0, dx, dy) setRenderingDefaults(gl) - // - + // z-slices to be render with multi render targets const dzMulti = Math.floor(dz / drawBuffers) * drawBuffers + // render multi target const programMulti = renderable.getProgram('draw') programMulti.use() - - console.time('gpu gaussian density 3d texture multi') for (let i = 0; i < dzMulti; i += drawBuffers) { ValueCell.update(uCurrentSlice, i) for (let k = 0; k < drawBuffers; ++k) { @@ -314,54 +167,185 @@ async function GaussianDensityMultiDrawBuffer(ctx: RuntimeContext, webgl: Contex } renderable.render('draw') } - console.timeEnd('gpu gaussian density 3d texture multi') + // render single target ValueCell.updateIfChanged(renderable.values.dDrawBuffers, 1) renderable.update() const programSingle = renderable.getProgram('draw') programSingle.use() - - console.time('gpu gaussian density 3d texture single') for (let i = dzMulti; i < dz; ++i) { ValueCell.update(uCurrentSlice, i) texture.attachFramebuffer(framebuffer, 0, i) renderable.render('draw') } - console.timeEnd('gpu gaussian density 3d texture single') // must detach framebuffer attachments before reading is possible for (let k = 0; k < drawBuffers; ++k) { texture.detachFramebuffer(framebuffer, k as TextureAttachment) } - framebuffer.destroy() // clean up - // throw new Error('foo') + framebuffer.destroy() // clean up return { texture, scale: Vec3.inverse(Vec3.zero(), delta), bbox: expandedBox, dim } } // -function fieldFromTexture3d(ctx: Context, texture: Texture, dim: Vec3) { +let webglContext: Context +function getWebGLContext() { + if (webglContext) return webglContext + const canvas = document.createElement('canvas') + const gl = getGLContext(canvas, { + alpha: true, + antialias: false, + depth: false, + preserveDrawingBuffer: true + }) + if (!gl) throw new Error('Could not create a WebGL rendering context') + webglContext = createContext(gl) + return webglContext +} + +async function prepareGaussianDensityData(ctx: RuntimeContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps) { + const { resolution, radiusOffset } = props + + const { indices, x, y, z } = position + const n = OrderedSet.size(indices) + + const positions = new Float32Array(n * 3) + const radii = new Float32Array(n) + + let maxRadius = 0 + + for (let i = 0; i < n; ++i) { + const j = OrderedSet.getAt(indices, i); + + positions[i * 3] = x[j] + positions[i * 3 + 1] = y[j] + positions[i * 3 + 2] = z[j] + const r = radius(j) + radiusOffset + if (maxRadius < r) maxRadius = r + radii[i] = r + + if (i % 10000 === 0 && ctx.shouldUpdate) { + await ctx.update({ message: 'preparing density data', current: i, max: n }) + } + } + + + const pad = maxRadius * 2 + resolution + const expandedBox = Box3D.expand(Box3D.empty(), box, Vec3.create(pad, pad, pad)); + const extent = Vec3.sub(Vec3.zero(), expandedBox.max, expandedBox.min) + + const delta = getDelta(expandedBox, resolution) + const dim = Vec3.zero() + Vec3.ceil(dim, Vec3.mul(dim, extent, delta)) + console.log('grid dim gpu', dim) + + return { drawCount: n, positions, radii, delta, expandedBox, dim } +} + +function getGaussianDensityRenderObject(webgl: Context, drawCount: number, positions: Float32Array, radii: Float32Array, box: Box3D, dimensions: Vec3, smoothness: number) { + const extent = Vec3.sub(Vec3.zero(), box.max, box.min) + + const values: GaussianDensityValues = { + drawCount: ValueCell.create(drawCount), + instanceCount: ValueCell.create(1), + + aRadius: ValueCell.create(radii), + aPosition: ValueCell.create(positions), + + uCurrentSlice: ValueCell.create(0), + uCurrentX: ValueCell.create(0), + uCurrentY: ValueCell.create(0), + uBboxMin: ValueCell.create(box.min), + uBboxMax: ValueCell.create(box.max), + uBboxSize: ValueCell.create(extent), + uGridDim: ValueCell.create(dimensions), + uAlpha: ValueCell.create(smoothness), + + dDrawBuffers: ValueCell.create(Math.min(8, webgl.maxDrawBuffers)), + } + const state: RenderableState = { + visible: true, + depthMask: false + } + + const renderObject = createGaussianDensityRenderObject(values, state) + + return renderObject +} + +function setRenderingDefaults(gl: GLRenderingContext) { + gl.disable(gl.CULL_FACE) + gl.frontFace(gl.CCW) + gl.cullFace(gl.BACK) + + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) + gl.blendEquation(gl.FUNC_ADD) + gl.enable(gl.BLEND) +} + +function fieldFromTexture2d(ctx: Context, texture: Texture, dim: Vec3) { const { gl } = ctx const [ dx, dy, dz ] = dim + const { width, height } = texture + const fboTexCols = Math.floor(width / dx) + + const space = Tensor.Space(dim, [2, 1, 0], Float32Array) + const data = space.create() + const field = Tensor.create(space, data) + + const image = new Uint8Array(width * height * 4) + + const framebuffer = createFramebuffer(ctx) + framebuffer.bind() + + texture.attachFramebuffer(framebuffer, 0) + gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, image) + + let idx = 0 + let tmpCol = 0 + let tmpRow = 0 + for (let iz = 0; iz < dz; ++iz) { + if (tmpCol >= fboTexCols ) { + tmpCol = 0 + tmpRow += dy + } + for (let iy = 0; iy < dy; ++iy) { + for (let ix = 0; ix < dx; ++ix) { + data[idx] = image[4 * (tmpCol * dx + (iy + tmpRow) * width + ix)] / 255 + idx++ + } + } + tmpCol++ + } + + framebuffer.destroy() + + return field +} + +function fieldFromTexture3d(ctx: Context, texture: Texture, dim: Vec3) { + const { gl } = ctx + const { width, height, depth } = texture const space = Tensor.Space(dim, [2, 1, 0], Float32Array) const data = space.create() const field = Tensor.create(space, data) - const slice = new Uint8Array(dx * dy * 4) + const slice = new Uint8Array(width * height * 4) const framebuffer = createFramebuffer(ctx) framebuffer.bind() let j = 0 - for (let i = 0; i < dz; ++i) { + for (let i = 0; i < depth; ++i) { texture.attachFramebuffer(framebuffer, 0, i) - gl.readPixels(0, 0, dx, dy, gl.RGBA, gl.UNSIGNED_BYTE, slice) - for (let iy = 0; iy < dim[1]; ++iy) { - for (let ix = 0; ix < dim[0]; ++ix) { - data[j] = slice[4 * (iy * dim[0] + ix)] / 255 + gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, slice) + for (let iy = 0; iy < height; ++iy) { + for (let ix = 0; ix < width; ++ix) { + data[j] = slice[4 * (iy * width + ix)] / 255 ++j } } diff --git a/src/mol-model/structure/structure/unit/gaussian-density.ts b/src/mol-model/structure/structure/unit/gaussian-density.ts index 821a828d9333bb5556d62074ff3b4ff052a47ee8..63e27cb5758c0a939df922ebdc430a1be301e1ff 100644 --- a/src/mol-model/structure/structure/unit/gaussian-density.ts +++ b/src/mol-model/structure/structure/unit/gaussian-density.ts @@ -16,7 +16,6 @@ export const GaussianDensityParams = { radiusOffset: NumberParam('Radius Offset', '', 0, 0, 10, 0.1), smoothness: NumberParam('Smoothness', '', 1.5, 0.5, 2.5, 0.1), useGpu: BooleanParam('Use GPU', '', true), - readSlices: BooleanParam('Read Slices', '', false), ignoreCache: BooleanParam('Ignore Cache', '', false), } export const DefaultGaussianDensityProps = paramDefaultValues(GaussianDensityParams)