Skip to content
Snippets Groups Projects
Commit 46da942f authored by Alexander Rose's avatar Alexander Rose
Browse files

wip, direct volume rendering

parent f9343a80
No related branches found
No related tags found
No related merge requests found
Showing
with 310 additions and 53 deletions
...@@ -23,4 +23,4 @@ const assemblyId = urlQueryParameter('assembly') ...@@ -23,4 +23,4 @@ const assemblyId = urlQueryParameter('assembly')
const pdbId = urlQueryParameter('pdb') const pdbId = urlQueryParameter('pdb')
if (pdbId) app.loadPdbIdOrMmcifUrl(pdbId, { assemblyId }) if (pdbId) app.loadPdbIdOrMmcifUrl(pdbId, { assemblyId })
// app.loadCcp4File() app.loadCcp4Url('http://localhost:8091/ngl/data/betaGal.mrc')
\ No newline at end of file \ No newline at end of file
...@@ -70,7 +70,7 @@ export async function StructureView(app: App, viewer: Viewer, models: ReadonlyAr ...@@ -70,7 +70,7 @@ export async function StructureView(app: App, viewer: Viewer, models: ReadonlyAr
const active: { [k: string]: boolean } = { const active: { [k: string]: boolean } = {
cartoon: true, cartoon: true,
point: false, point: false,
surface: true, surface: false,
ballAndStick: false, ballAndStick: false,
carbohydrate: false, carbohydrate: false,
spacefill: false, spacefill: false,
......
...@@ -10,8 +10,8 @@ import { App } from './app'; ...@@ -10,8 +10,8 @@ import { App } from './app';
import { Progress } from 'mol-task'; import { Progress } from 'mol-task';
import { VolumeData } from 'mol-model/volume'; import { VolumeData } from 'mol-model/volume';
import { VolumeRepresentation } from 'mol-geo/representation/volume'; import { VolumeRepresentation } from 'mol-geo/representation/volume';
import IsosurfaceVisual from 'mol-geo/representation/volume/isosurface'; import { IsosurfaceRepresentation } from 'mol-geo/representation/volume/isosurface-mesh';
import { Vec3 } from 'mol-math/linear-algebra'; import { DirectVolumeRepresentation } from 'mol-geo/representation/volume/direct-volume';
export interface VolumeView { export interface VolumeView {
readonly app: App readonly app: App
...@@ -28,19 +28,19 @@ export interface VolumeView { ...@@ -28,19 +28,19 @@ export interface VolumeView {
destroy: () => void destroy: () => void
} }
interface StructureViewProps { interface VolumeViewProps {
assemblyId?: string
symmetryFeatureId?: number
} }
export async function VolumeView(app: App, viewer: Viewer, volume: VolumeData, props: StructureViewProps = {}): Promise<VolumeView> { export async function VolumeView(app: App, viewer: Viewer, volume: VolumeData, props: VolumeViewProps = {}): Promise<VolumeView> {
const active: { [k: string]: boolean } = { const active: { [k: string]: boolean } = {
isosurface: true, isosurface: true,
volume: false, directVolume: false,
} }
const volumeRepresentations: { [k: string]: VolumeRepresentation<any> } = { const volumeRepresentations: { [k: string]: VolumeRepresentation<any> } = {
isosurface: VolumeRepresentation(IsosurfaceVisual), isosurface: IsosurfaceRepresentation(),
directVolume: DirectVolumeRepresentation(),
} }
const updated: BehaviorSubject<null> = new BehaviorSubject<null>(null) const updated: BehaviorSubject<null> = new BehaviorSubject<null>(null)
......
...@@ -13,8 +13,9 @@ import { downloadCif } from './helpers' ...@@ -13,8 +13,9 @@ import { downloadCif } from './helpers'
import CIF from 'mol-io/reader/cif' import CIF from 'mol-io/reader/cif'
import { DensityServer_Data_Database } from 'mol-io/reader/cif/schema/density-server'; import { DensityServer_Data_Database } from 'mol-io/reader/cif/schema/density-server';
import { Table } from 'mol-data/db'; import { Table } from 'mol-data/db';
import { computeVolumeSurface } from 'mol-geo/representation/volume/isosurface'; import { createVolumeSurface } from 'mol-geo/representation/volume/isosurface-mesh';
import { StringBuilder } from 'mol-util'; import { StringBuilder } from 'mol-util';
import { Task } from 'mol-task';
require('util.promisify').shim(); require('util.promisify').shim();
const writeFileAsync = util.promisify(fs.writeFile); const writeFileAsync = util.promisify(fs.writeFile);
...@@ -37,7 +38,7 @@ function print(data: Volume) { ...@@ -37,7 +38,7 @@ function print(data: Volume) {
} }
async function doMesh(data: Volume, filename: string) { async function doMesh(data: Volume, filename: string) {
const mesh = await computeVolumeSurface(data.volume, VolumeIsoValue.relative(data.volume.dataStats, 1.5)).run(); const mesh = await Task.create('', ctx => createVolumeSurface(ctx, data.volume, VolumeIsoValue.relative(data.volume.dataStats, 1.5))).run();
console.log({ vc: mesh.vertexCount, tc: mesh.triangleCount }); console.log({ vc: mesh.vertexCount, tc: mesh.triangleCount });
// Export the mesh in OBJ format. // Export the mesh in OBJ format.
......
...@@ -85,6 +85,7 @@ export namespace DirectVolume { ...@@ -85,6 +85,7 @@ export namespace DirectVolume {
} }
export function updateValues(values: DirectVolumeValues, props: Props) { export function updateValues(values: DirectVolumeValues, props: Props) {
console.log('DirectVolumeValues', props, values)
ValueCell.updateIfChanged(values.uIsoValue, props.isoValue) ValueCell.updateIfChanged(values.uIsoValue, props.isoValue)
ValueCell.updateIfChanged(values.uAlpha, props.alpha) ValueCell.updateIfChanged(values.uAlpha, props.alpha)
ValueCell.updateIfChanged(values.dUseFog, props.useFog) ValueCell.updateIfChanged(values.dUseFog, props.useFog)
......
...@@ -18,7 +18,7 @@ export function getControlPointsFromString(s: string): ControlPoint[] { ...@@ -18,7 +18,7 @@ export function getControlPointsFromString(s: string): ControlPoint[] {
return { x: parseFloat(ps[0]), alpha: parseFloat(ps[1]) } return { x: parseFloat(ps[0]), alpha: parseFloat(ps[1]) }
}) })
} }
// TODO move core function to mol-view/color
export function createTransferFunctionTexture(controlPoints: ControlPoint[], texture?: ValueCell<TextureImage>): ValueCell<TextureImage> { export function createTransferFunctionTexture(controlPoints: ControlPoint[], texture?: ValueCell<TextureImage>): ValueCell<TextureImage> {
const cp = [ const cp = [
{ x: 0, alpha: 0 }, { x: 0, alpha: 0 },
......
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { VolumeData } from 'mol-model/volume'
import { RuntimeContext } from 'mol-task'
import { VolumeVisual, VolumeRepresentation } from '.';
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, RangeParam } from 'mol-view/parameter';
import { ValueCell } from 'mol-util';
import { DirectVolume } from '../../geometry/direct-volume/direct-volume';
import { Vec2, Vec3, Tensor } from 'mol-math/linear-algebra';
import { Box3D } from 'mol-math/geometry';
import { createImageData } from 'mol-gl/webgl/context';
import { debugTexture } from 'mol-gl/util';
function getFlattedVolumeLayout(dim: Vec3, maxTextureSize = 4096) {
let width = 0
let height = dim[1]
let rows = 1
let columns = dim[0]
if (maxTextureSize < dim[0] * dim[2]) {
columns = Math.floor(maxTextureSize / dim[0])
rows = Math.ceil(dim[2] / columns)
width = columns * dim[0]
height *= rows
} else {
width = dim[0] * dim[2]
}
width += columns // horizontal padding
height += rows // vertical padding
return { width, height, columns, rows }
}
// let foo = 0
function createFlattendVolumeTexture(tensor: Tensor, itemSize = 4) {
const { space, data } = tensor
const dim = space.dimensions as Vec3
const { get } = space
const { width, height, columns, rows } = getFlattedVolumeLayout(dim)
const array = new Uint8Array(width * height * itemSize)
const textureImage = { array, width, height }
const [ xl, yl, zl ] = dim
const xlp = xl + 1
const ylp = yl + 1
function setTex(value: number, x: number, y: number, z: number) {
const column = Math.floor(((z * xlp) % width) / xlp)
const row = Math.floor((z * xlp) / width)
const px = column * xlp + x
// const py = row * ylp + y
const index = itemSize * ((row * ylp * width) + (y * width) + px);
array[index] = value * 255;
array[index + 1] = value * 255;
array[index + 3] = value;
// if (foo % 1000 === 0) {
// console.log(value * 255, x, y, z, index, '|', column, row);
// }
// ++foo;
}
console.log('dim', dim)
console.log('layout', { width, height, columns, rows })
for (let z = 0; z < zl; ++z) {
for (let y = 0; y < yl; ++y) {
for (let x = 0; x < xl; ++x) {
setTex(get(data, x, y, z), x, y, z)
}
}
}
return textureImage
}
export function createDirectVolume(ctx: RuntimeContext, volume: VolumeData, directVolume?: DirectVolume) {
const gridDimension = volume.data.space.dimensions as Vec3
// const textureImage = createTextureImage(1, 4)
const textureImage = createFlattendVolumeTexture(volume.data)
const transform = VolumeData.getGridToCartesianTransform(volume)
console.log('textureImage', textureImage)
debugTexture(createImageData(textureImage.array, textureImage.width, textureImage.height), 1/3)
const bbox = Box3D.empty()
Box3D.add(bbox, gridDimension)
Box3D.transform(bbox, bbox, transform)
const dim = Vec3.create(gridDimension[0] + 1, gridDimension[1] + 1, gridDimension[2])
if (directVolume) {
ValueCell.update(directVolume.gridDimension, dim)
ValueCell.update(directVolume.gridTexture, textureImage)
ValueCell.update(directVolume.gridTextureDim, Vec2.set(directVolume.gridTextureDim.ref.value, textureImage.width, textureImage.height))
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)
} else {
directVolume = {
kind: 'direct-volume' as 'direct-volume',
gridDimension: ValueCell.create(dim),
gridTexture: ValueCell.create(textureImage),
gridTextureDim: ValueCell.create(Vec2.create(textureImage.width, textureImage.height)),
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),
}
}
console.log('gridDimension', dim)
console.log('gridTextureDim', textureImage.width, textureImage.height)
console.log('boundingBox', bbox)
console.log('transform', transform)
return directVolume;
}
export const DirectVolumeParams = {
...Geometry.Params,
...DirectVolume.Params,
isoValue: RangeParam('Iso Value', '', 2, -15, 15, 0.01),
}
export const DefaultDirectVolumeProps = paramDefaultValues(DirectVolumeParams)
export type DirectVolumeProps = typeof DefaultDirectVolumeProps
export function DirectVolumeVisual(): VolumeVisual<DirectVolumeProps> {
let currentProps = DefaultDirectVolumeProps
let renderObject: DirectVolumeRenderObject
let currentVolume: VolumeData
let directVolume: DirectVolume
async function create(ctx: RuntimeContext, volume: VolumeData, props: Partial<DirectVolumeProps> = {}) {
currentProps = { ...DefaultDirectVolumeProps, ...props }
directVolume = await createDirectVolume(ctx, volume, directVolume)
const values = await DirectVolume.createValues(ctx, directVolume, currentProps)
const state = createRenderableState(currentProps)
renderObject = createDirectVolumeRenderObject(values, state)
}
async function update(ctx: RuntimeContext, props: Partial<DirectVolumeProps> = {}) {
console.log('props', props)
const newProps = { ...currentProps, ...props }
DirectVolume.updateValues(renderObject.values, newProps)
updateRenderableState(renderObject.state, newProps)
currentProps = newProps
}
return {
get renderObject () { return renderObject },
async createOrUpdate(ctx: RuntimeContext, props: Partial<DirectVolumeProps> = {}, volume?: VolumeData) {
if (!volume && !currentVolume) {
throw new Error('missing volume')
} else if (volume && (!currentVolume || !renderObject)) {
currentVolume = volume
await create(ctx, volume, props)
} else if (volume && volume !== currentVolume) {
currentVolume = volume
await create(ctx, volume, props)
} else {
await update(ctx, props)
}
currentProps = { ...DefaultDirectVolumeProps, ...props }
},
getLoci(pickingId: PickingId) {
// TODO
return EmptyLoci
},
mark(loci: Loci, action: MarkerAction) {
// TODO
return false
},
destroy() {
// TODO
}
}
}
export function DirectVolumeRepresentation(): VolumeRepresentation<DirectVolumeProps> {
let currentProps: DirectVolumeProps
const volumeRepr = VolumeRepresentation(DirectVolumeVisual)
return {
label: 'Direct Volume',
params: DirectVolumeParams,
get renderObjects() {
return [ ...volumeRepr.renderObjects ]
},
get props() {
return { ...volumeRepr.props }
},
createOrUpdate: (props: Partial<DirectVolumeProps> = {}, volume?: VolumeData) => {
currentProps = Object.assign({}, DefaultDirectVolumeProps, currentProps, props)
return volumeRepr.createOrUpdate(currentProps, volume)
},
getLoci: (pickingId: PickingId) => {
return volumeRepr.getLoci(pickingId)
},
mark: (loci: Loci, action: MarkerAction) => {
return volumeRepr.mark(loci, action)
},
destroy() {
volumeRepr.destroy()
}
}
}
\ No newline at end of file
...@@ -12,7 +12,6 @@ import { Loci, EmptyLoci } from 'mol-model/loci'; ...@@ -12,7 +12,6 @@ import { Loci, EmptyLoci } from 'mol-model/loci';
import { MarkerAction } from '../../geometry/marker-data'; import { MarkerAction } from '../../geometry/marker-data';
import { Geometry } from '../../geometry/geometry'; import { Geometry } from '../../geometry/geometry';
import { paramDefaultValues } from 'mol-view/parameter'; import { paramDefaultValues } from 'mol-view/parameter';
import { IsosurfaceParams } from './isosurface';
export interface VolumeVisual<P extends RepresentationProps = {}> extends Visual<VolumeData, P> { } export interface VolumeVisual<P extends RepresentationProps = {}> extends Visual<VolumeData, P> { }
...@@ -20,7 +19,6 @@ export interface VolumeRepresentation<P extends RepresentationProps = {}> extend ...@@ -20,7 +19,6 @@ export interface VolumeRepresentation<P extends RepresentationProps = {}> extend
export const VolumeParams = { export const VolumeParams = {
...Geometry.Params, ...Geometry.Params,
...IsosurfaceParams
} }
export const DefaultVolumeProps = paramDefaultValues(VolumeParams) export const DefaultVolumeProps = paramDefaultValues(VolumeParams)
export type VolumeProps = typeof DefaultVolumeProps export type VolumeProps = typeof DefaultVolumeProps
...@@ -52,7 +50,7 @@ export function VolumeRepresentation<P extends VolumeProps>(visualCtor: (volumeD ...@@ -52,7 +50,7 @@ export function VolumeRepresentation<P extends VolumeProps>(visualCtor: (volumeD
} }
return { return {
label: 'Volume mesh', label: 'Volume',
params: VolumeParams, params: VolumeParams,
get renderObjects() { get renderObjects() {
return visual && visual.renderObject ? [ visual.renderObject ] : [] return visual && visual.renderObject ? [ visual.renderObject ] : []
......
...@@ -6,10 +6,10 @@ ...@@ -6,10 +6,10 @@
*/ */
import { VolumeData, VolumeIsoValue } from 'mol-model/volume' import { VolumeData, VolumeIsoValue } from 'mol-model/volume'
import { Task, RuntimeContext } from 'mol-task' import { RuntimeContext } from 'mol-task'
import { computeMarchingCubesMesh } from '../../util/marching-cubes/algorithm'; import { computeMarchingCubesMesh } from '../../util/marching-cubes/algorithm';
import { Mesh } from '../../geometry/mesh/mesh'; import { Mesh } from '../../geometry/mesh/mesh';
import { VolumeVisual } from '.'; import { VolumeVisual, VolumeRepresentation } from '.';
import { createMeshRenderObject, MeshRenderObject } from 'mol-gl/render-object'; import { createMeshRenderObject, MeshRenderObject } from 'mol-gl/render-object';
import { PickingId } from '../../geometry/picking'; import { PickingId } from '../../geometry/picking';
import { MarkerAction } from '../../geometry/marker-data'; import { MarkerAction } from '../../geometry/marker-data';
...@@ -21,8 +21,7 @@ import { createRenderableState, updateRenderableState } from '../../geometry/geo ...@@ -21,8 +21,7 @@ import { createRenderableState, updateRenderableState } from '../../geometry/geo
import { paramDefaultValues, NumberParam } from 'mol-view/parameter'; import { paramDefaultValues, NumberParam } from 'mol-view/parameter';
import { ValueCell } from 'mol-util'; import { ValueCell } from 'mol-util';
export function computeVolumeSurface(volume: VolumeData, isoValue: VolumeIsoValue, mesh?: Mesh) { export async function createVolumeSurface(ctx: RuntimeContext, volume: VolumeData, isoValue: VolumeIsoValue, mesh?: Mesh) {
return Task.create<Mesh>('Volume Surface', async ctx => {
ctx.update({ message: 'Marching cubes...' }); ctx.update({ message: 'Marching cubes...' });
const surface = await computeMarchingCubesMesh({ const surface = await computeMarchingCubesMesh({
...@@ -36,7 +35,6 @@ export function computeVolumeSurface(volume: VolumeData, isoValue: VolumeIsoValu ...@@ -36,7 +35,6 @@ export function computeVolumeSurface(volume: VolumeData, isoValue: VolumeIsoValu
Mesh.computeNormalsImmediate(surface) Mesh.computeNormalsImmediate(surface)
return surface; return surface;
});
} }
export const IsosurfaceParams = { export const IsosurfaceParams = {
...@@ -46,7 +44,7 @@ export const IsosurfaceParams = { ...@@ -46,7 +44,7 @@ export const IsosurfaceParams = {
export const DefaultIsosurfaceProps = paramDefaultValues(IsosurfaceParams) export const DefaultIsosurfaceProps = paramDefaultValues(IsosurfaceParams)
export type IsosurfaceProps = typeof DefaultIsosurfaceProps export type IsosurfaceProps = typeof DefaultIsosurfaceProps
export default function IsosurfaceVisual(): VolumeVisual<IsosurfaceProps> { export function IsosurfaceVisual(): VolumeVisual<IsosurfaceProps> {
let currentProps = DefaultIsosurfaceProps let currentProps = DefaultIsosurfaceProps
let renderObject: MeshRenderObject let renderObject: MeshRenderObject
let currentVolume: VolumeData let currentVolume: VolumeData
...@@ -55,7 +53,7 @@ export default function IsosurfaceVisual(): VolumeVisual<IsosurfaceProps> { ...@@ -55,7 +53,7 @@ export default function IsosurfaceVisual(): VolumeVisual<IsosurfaceProps> {
async function create(ctx: RuntimeContext, volume: VolumeData, props: Partial<IsosurfaceProps> = {}) { async function create(ctx: RuntimeContext, volume: VolumeData, props: Partial<IsosurfaceProps> = {}) {
currentProps = { ...DefaultIsosurfaceProps, ...props } currentProps = { ...DefaultIsosurfaceProps, ...props }
mesh = await computeVolumeSurface(volume, VolumeIsoValue.relative(volume.dataStats, currentProps.isoValue)).runAsChild(ctx) mesh = await createVolumeSurface(ctx, volume, VolumeIsoValue.relative(volume.dataStats, currentProps.isoValue))
const locationIt = LocationIterator(1, 1, () => NullLocation) const locationIt = LocationIterator(1, 1, () => NullLocation)
const transform = createIdentityTransform() const transform = createIdentityTransform()
...@@ -74,7 +72,7 @@ export default function IsosurfaceVisual(): VolumeVisual<IsosurfaceProps> { ...@@ -74,7 +72,7 @@ export default function IsosurfaceVisual(): VolumeVisual<IsosurfaceProps> {
if (newProps.isoValue !== currentProps.isoValue) createMesh = true if (newProps.isoValue !== currentProps.isoValue) createMesh = true
if (createMesh) { if (createMesh) {
mesh = await computeVolumeSurface(currentVolume, VolumeIsoValue.relative(currentVolume.dataStats, currentProps.isoValue), mesh).runAsChild(ctx) mesh = await createVolumeSurface(ctx, currentVolume, VolumeIsoValue.relative(currentVolume.dataStats, currentProps.isoValue), mesh)
ValueCell.update(renderObject.values.drawCount, mesh.triangleCount * 3) ValueCell.update(renderObject.values.drawCount, mesh.triangleCount * 3)
} }
...@@ -82,7 +80,6 @@ export default function IsosurfaceVisual(): VolumeVisual<IsosurfaceProps> { ...@@ -82,7 +80,6 @@ export default function IsosurfaceVisual(): VolumeVisual<IsosurfaceProps> {
updateRenderableState(renderObject.state, newProps) updateRenderableState(renderObject.state, newProps)
currentProps = newProps currentProps = newProps
return true
} }
return { return {
...@@ -101,7 +98,6 @@ export default function IsosurfaceVisual(): VolumeVisual<IsosurfaceProps> { ...@@ -101,7 +98,6 @@ export default function IsosurfaceVisual(): VolumeVisual<IsosurfaceProps> {
} }
currentProps = { ...DefaultIsosurfaceProps, ...props } currentProps = { ...DefaultIsosurfaceProps, ...props }
}, },
getLoci(pickingId: PickingId) { getLoci(pickingId: PickingId) {
// TODO // TODO
...@@ -116,3 +112,31 @@ export default function IsosurfaceVisual(): VolumeVisual<IsosurfaceProps> { ...@@ -116,3 +112,31 @@ export default function IsosurfaceVisual(): VolumeVisual<IsosurfaceProps> {
} }
} }
} }
export function IsosurfaceRepresentation(): VolumeRepresentation<IsosurfaceProps> {
let currentProps: IsosurfaceProps
const volumeRepr = VolumeRepresentation(IsosurfaceVisual)
return {
label: 'Isosurface',
params: IsosurfaceParams,
get renderObjects() {
return [ ...volumeRepr.renderObjects ]
},
get props() {
return { ...volumeRepr.props }
},
createOrUpdate: (props: Partial<IsosurfaceProps> = {}, volume?: VolumeData) => {
currentProps = Object.assign({}, DefaultIsosurfaceProps, currentProps, props)
return volumeRepr.createOrUpdate(currentProps, volume)
},
getLoci: (pickingId: PickingId) => {
return volumeRepr.getLoci(pickingId)
},
mark: (loci: Loci, action: MarkerAction) => {
return volumeRepr.mark(loci, action)
},
destroy() {
volumeRepr.destroy()
}
}
}
\ No newline at end of file
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
import { Renderable, RenderableState, createRenderable } from '../renderable' import { Renderable, RenderableState, createRenderable } from '../renderable'
import { Context } from '../webgl/context'; import { Context } from '../webgl/context';
import { createRenderItem } from '../webgl/render-item'; import { createRenderItem } from '../webgl/render-item';
import { AttributeSpec, Values, UniformSpec, GlobalUniformSchema, InternalSchema, TextureSpec, ValueSpec, ElementsSpec, DefineSpec } from './schema'; import { AttributeSpec, Values, UniformSpec, GlobalUniformSchema, InternalSchema, TextureSpec, ValueSpec, ElementsSpec, DefineSpec, InternalValues } from './schema';
import { DirectVolumeShaderCode } from '../shader-code'; import { DirectVolumeShaderCode } from '../shader-code';
import { ValueCell } from 'mol-util'; import { ValueCell } from 'mol-util';
...@@ -37,7 +37,8 @@ export type DirectVolumeValues = Values<DirectVolumeSchema> ...@@ -37,7 +37,8 @@ export type DirectVolumeValues = Values<DirectVolumeSchema>
export function DirectVolumeRenderable(ctx: Context, id: number, values: DirectVolumeValues, state: RenderableState): Renderable<DirectVolumeValues> { export function DirectVolumeRenderable(ctx: Context, id: number, values: DirectVolumeValues, state: RenderableState): Renderable<DirectVolumeValues> {
const schema = { ...GlobalUniformSchema, ...InternalSchema, ...DirectVolumeSchema } const schema = { ...GlobalUniformSchema, ...InternalSchema, ...DirectVolumeSchema }
const internalValues = { const internalValues: InternalValues = {
dWebGL2: ValueCell.create(ctx.isWebGL2),
uObjectId: ValueCell.create(id) uObjectId: ValueCell.create(id)
} }
const shaderCode = DirectVolumeShaderCode const shaderCode = DirectVolumeShaderCode
......
...@@ -7,10 +7,12 @@ ...@@ -7,10 +7,12 @@
import { Renderable, RenderableState, createRenderable } from '../renderable' import { Renderable, RenderableState, createRenderable } from '../renderable'
import { Context } from '../webgl/context'; import { Context } from '../webgl/context';
import { createRenderItem } from '../webgl/render-item'; import { createRenderItem } from '../webgl/render-item';
import { AttributeSpec, Values, UniformSpec, ValueSpec } from './schema'; import { AttributeSpec, Values, UniformSpec, ValueSpec, DefineSpec } from './schema';
import { GaussianDensityShaderCode } from '../shader-code'; import { GaussianDensityShaderCode } from '../shader-code';
export const GaussianDensitySchema = { export const GaussianDensitySchema = {
dWebGL2: DefineSpec('boolean'),
drawCount: ValueSpec('number'), drawCount: ValueSpec('number'),
instanceCount: ValueSpec('number'), instanceCount: ValueSpec('number'),
...@@ -32,7 +34,7 @@ export type GaussianDensityValues = Values<GaussianDensitySchema> ...@@ -32,7 +34,7 @@ export type GaussianDensityValues = Values<GaussianDensitySchema>
export function GaussianDensityRenderable(ctx: Context, id: number, values: GaussianDensityValues, state: RenderableState): Renderable<GaussianDensityValues> { export function GaussianDensityRenderable(ctx: Context, id: number, values: GaussianDensityValues, state: RenderableState): Renderable<GaussianDensityValues> {
const schema = { ...GaussianDensitySchema } const schema = { ...GaussianDensitySchema }
const shaderCode = GaussianDensityShaderCode const shaderCode = GaussianDensityShaderCode
const renderItem = createRenderItem(ctx, 'points', shaderCode, schema, { ...values }) const renderItem = createRenderItem(ctx, 'points', shaderCode, schema, values)
return createRenderable(renderItem, values, state); return createRenderable(renderItem, values, state);
} }
\ No newline at end of file
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
import { Renderable, RenderableState, createRenderable } from '../renderable' import { Renderable, RenderableState, createRenderable } from '../renderable'
import { Context } from '../webgl/context'; import { Context } from '../webgl/context';
import { createRenderItem } from '../webgl/render-item'; import { createRenderItem } from '../webgl/render-item';
import { GlobalUniformSchema, BaseSchema, AttributeSpec, DefineSpec, Values, InternalSchema, SizeSchema, ElementsSpec } from './schema'; import { GlobalUniformSchema, BaseSchema, AttributeSpec, DefineSpec, Values, InternalSchema, SizeSchema, ElementsSpec, InternalValues } from './schema';
import { ValueCell } from 'mol-util'; import { ValueCell } from 'mol-util';
import { LinesShaderCode } from '../shader-code'; import { LinesShaderCode } from '../shader-code';
...@@ -27,7 +27,8 @@ export type LinesValues = Values<LinesSchema> ...@@ -27,7 +27,8 @@ export type LinesValues = Values<LinesSchema>
export function LinesRenderable(ctx: Context, id: number, values: LinesValues, state: RenderableState): Renderable<LinesValues> { export function LinesRenderable(ctx: Context, id: number, values: LinesValues, state: RenderableState): Renderable<LinesValues> {
const schema = { ...GlobalUniformSchema, ...InternalSchema, ...LinesSchema } const schema = { ...GlobalUniformSchema, ...InternalSchema, ...LinesSchema }
const internalValues = { const internalValues: InternalValues = {
dWebGL2: ValueCell.create(ctx.isWebGL2),
uObjectId: ValueCell.create(id) uObjectId: ValueCell.create(id)
} }
const shaderCode = LinesShaderCode const shaderCode = LinesShaderCode
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
import { Renderable, RenderableState, createRenderable } from '../renderable' import { Renderable, RenderableState, createRenderable } from '../renderable'
import { Context } from '../webgl/context'; import { Context } from '../webgl/context';
import { createRenderItem } from '../webgl/render-item'; import { createRenderItem } from '../webgl/render-item';
import { GlobalUniformSchema, BaseSchema, AttributeSpec, ElementsSpec, DefineSpec, Values, InternalSchema } from './schema'; import { GlobalUniformSchema, BaseSchema, AttributeSpec, ElementsSpec, DefineSpec, Values, InternalSchema, InternalValues } from './schema';
import { MeshShaderCode } from '../shader-code'; import { MeshShaderCode } from '../shader-code';
import { ValueCell } from 'mol-util'; import { ValueCell } from 'mol-util';
...@@ -25,7 +25,8 @@ export type MeshValues = Values<MeshSchema> ...@@ -25,7 +25,8 @@ export type MeshValues = Values<MeshSchema>
export function MeshRenderable(ctx: Context, id: number, values: MeshValues, state: RenderableState): Renderable<MeshValues> { export function MeshRenderable(ctx: Context, id: number, values: MeshValues, state: RenderableState): Renderable<MeshValues> {
const schema = { ...GlobalUniformSchema, ...InternalSchema, ...MeshSchema } const schema = { ...GlobalUniformSchema, ...InternalSchema, ...MeshSchema }
const internalValues = { const internalValues: InternalValues = {
dWebGL2: ValueCell.create(ctx.isWebGL2),
uObjectId: ValueCell.create(id) uObjectId: ValueCell.create(id)
} }
const shaderCode = MeshShaderCode const shaderCode = MeshShaderCode
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
import { Renderable, RenderableState, createRenderable } from '../renderable' import { Renderable, RenderableState, createRenderable } from '../renderable'
import { Context } from '../webgl/context'; import { Context } from '../webgl/context';
import { createRenderItem } from '../webgl/render-item'; import { createRenderItem } from '../webgl/render-item';
import { GlobalUniformSchema, BaseSchema, AttributeSpec, UniformSpec, DefineSpec, Values, InternalSchema, SizeSchema } from './schema'; import { GlobalUniformSchema, BaseSchema, AttributeSpec, UniformSpec, DefineSpec, Values, InternalSchema, SizeSchema, InternalValues } from './schema';
import { PointsShaderCode } from '../shader-code'; import { PointsShaderCode } from '../shader-code';
import { ValueCell } from 'mol-util'; import { ValueCell } from 'mol-util';
...@@ -24,7 +24,8 @@ export type PointsValues = Values<PointsSchema> ...@@ -24,7 +24,8 @@ export type PointsValues = Values<PointsSchema>
export function PointsRenderable(ctx: Context, id: number, values: PointsValues, state: RenderableState): Renderable<PointsValues> { export function PointsRenderable(ctx: Context, id: number, values: PointsValues, state: RenderableState): Renderable<PointsValues> {
const schema = { ...GlobalUniformSchema, ...InternalSchema, ...PointsSchema } const schema = { ...GlobalUniformSchema, ...InternalSchema, ...PointsSchema }
const internalValues = { const internalValues: InternalValues = {
dWebGL2: ValueCell.create(ctx.isWebGL2),
uObjectId: ValueCell.create(id) uObjectId: ValueCell.create(id)
} }
const shaderCode = PointsShaderCode const shaderCode = PointsShaderCode
......
...@@ -141,8 +141,11 @@ export type GlobalUniformSchema = typeof GlobalUniformSchema ...@@ -141,8 +141,11 @@ export type GlobalUniformSchema = typeof GlobalUniformSchema
export type GlobalUniformValues = { [k in keyof GlobalUniformSchema]: ValueCell<any> } export type GlobalUniformValues = { [k in keyof GlobalUniformSchema]: ValueCell<any> }
export const InternalSchema = { export const InternalSchema = {
dWebGL2: DefineSpec('boolean'),
uObjectId: UniformSpec('i'), uObjectId: UniformSpec('i'),
} }
export type InternalSchema = typeof InternalSchema
export type InternalValues = { [k in keyof InternalSchema]: ValueCell<any> }
export const ColorSchema = { export const ColorSchema = {
aColor: AttributeSpec('float32', 3, 0), aColor: AttributeSpec('float32', 3, 0),
......
...@@ -84,13 +84,13 @@ vec3 palette1(in float t) { ...@@ -84,13 +84,13 @@ vec3 palette1(in float t) {
vec4 textureVal(vec3 pos) { vec4 textureVal(vec3 pos) {
float zSlice0 = floor(pos.z * uGridDim.z); float zSlice0 = floor(pos.z * uGridDim.z);
float column0 = myMod(zSlice0 * uGridDim.x, uGridTexDim.x) / uGridDim.x; float column0 = myMod(zSlice0 * uGridDim.x, uGridTexDim.x) / uGridDim.x;
float row0 = floor(myDiv((zSlice0 * uGridDim.x), uGridTexDim.x)); float row0 = floor(myDiv(zSlice0 * uGridDim.x, uGridTexDim.x));
vec2 coord0 = (vec2(column0 * uGridDim.x, row0 * uGridDim.y) + (pos.xy * uGridDim.xy)) / uGridTexDim; vec2 coord0 = (vec2(column0 * uGridDim.x, row0 * uGridDim.y) + (pos.xy * uGridDim.xy)) / uGridTexDim;
vec4 color0 = texture2D(tGridTex, coord0); vec4 color0 = texture2D(tGridTex, coord0);
float zSlice1 = zSlice0 + 1.0; float zSlice1 = zSlice0 + 1.0;
float column1 = myMod(zSlice1 * uGridDim.x, uGridTexDim.x) / uGridDim.x; float column1 = myMod(zSlice1 * uGridDim.x, uGridTexDim.x) / uGridDim.x;
float row1 = floor(myDiv((zSlice1 * uGridDim.x), uGridTexDim.x)); float row1 = floor(myDiv(zSlice1 * uGridDim.x, uGridTexDim.x));
vec2 coord1 = (vec2(column1 * uGridDim.x, row1 * uGridDim.y) + (pos.xy * uGridDim.xy)) / uGridTexDim; vec2 coord1 = (vec2(column1 * uGridDim.x, row1 * uGridDim.y) + (pos.xy * uGridDim.xy)) / uGridTexDim;
vec4 color1 = texture2D(tGridTex, coord1); vec4 color1 = texture2D(tGridTex, coord1);
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Alexander Rose <alexander.rose@weirdbyte.de>
*/ */
function debugTexture(imageData: ImageData, scale = 1) { export function debugTexture(imageData: ImageData, scale = 1) {
const canvas = document.createElement('canvas') const canvas = document.createElement('canvas')
canvas.width = imageData.width canvas.width = imageData.width
canvas.height = imageData.height canvas.height = imageData.height
...@@ -20,6 +20,7 @@ function debugTexture(imageData: ImageData, scale = 1) { ...@@ -20,6 +20,7 @@ function debugTexture(imageData: ImageData, scale = 1) {
img.style.position = 'absolute' img.style.position = 'absolute'
img.style.top = '0px' img.style.top = '0px'
img.style.left = '0px' img.style.left = '0px'
img.style.border = 'solid grey'
document.body.appendChild(img) document.body.appendChild(img)
}, 'image/png') }, 'image/png')
} }
\ No newline at end of file
...@@ -60,7 +60,12 @@ export async function GaussianDensityGPU(ctx: RuntimeContext, position: Position ...@@ -60,7 +60,12 @@ export async function GaussianDensityGPU(ctx: RuntimeContext, position: Position
// //
// TODO do in OffscreenCanvas (https://www.chromestatus.com/feature/5681560598609920)?
const webgl = getWebGLContext()
const values: GaussianDensityValues = { const values: GaussianDensityValues = {
dWebGL2: ValueCell.create(webgl.isWebGL2),
drawCount: ValueCell.create(n), drawCount: ValueCell.create(n),
instanceCount: ValueCell.create(1), instanceCount: ValueCell.create(1),
...@@ -81,16 +86,13 @@ export async function GaussianDensityGPU(ctx: RuntimeContext, position: Position ...@@ -81,16 +86,13 @@ export async function GaussianDensityGPU(ctx: RuntimeContext, position: Position
depthMask: false depthMask: false
} }
// TODO do in OffscreenCanvas (https://www.chromestatus.com/feature/5681560598609920)
const webgl = getWebGLContext()
const renderObject = createGaussianDensityRenderObject(values, state) const renderObject = createGaussianDensityRenderObject(values, state)
const renderable = createRenderable(webgl, renderObject) const renderable = createRenderable(webgl, renderObject)
// //
// TODO fallback to lower resolution when texture size is not large enough // TODO fallback to lower resolution when texture size is not large enough
const maxTexSize = 1024 // webgl.maxTextureSize const maxTexSize = webgl.maxTextureSize
let fboTexDimX = 0 let fboTexDimX = 0
let fboTexDimY = dim[1] let fboTexDimY = dim[1]
let fboTexRows = 1 let fboTexRows = 1
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment