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

wip, isosurface renderable

parent 4a39fac4
No related branches found
No related tags found
No related merge requests found
......@@ -21,6 +21,7 @@ import { TransformData } from './transform-data';
import { Theme } from 'mol-theme/theme';
import { RenderObjectValuesType } from 'mol-gl/render-object';
import { ValueOf } from 'mol-util/type-helpers';
import { Isosurface } from './isosurface/isosurface';
export type GeometryKindType = {
'mesh': Mesh,
......@@ -29,6 +30,7 @@ export type GeometryKindType = {
'text': Text,
'lines': Lines,
'direct-volume': DirectVolume,
'isosurface': Isosurface,
}
export type GeometryKindParams = {
'mesh': Mesh.Params,
......@@ -37,6 +39,7 @@ export type GeometryKindParams = {
'text': Text.Params,
'lines': Lines.Params,
'direct-volume': DirectVolume.Params,
'isosurface': Isosurface.Params,
}
export type GeometryKind = keyof GeometryKindType
export type Geometry = ValueOf<GeometryKindType>
......@@ -63,6 +66,7 @@ export namespace Geometry {
case 'text': return geometry.charCount * 2 * 3
case 'lines': return geometry.lineCount * 2 * 3
case 'direct-volume': return 12 * 3
case 'isosurface': return geometry.vertexCount.ref.value * 3
}
}
......@@ -76,6 +80,8 @@ export namespace Geometry {
return getDrawCount(geometry) === 0 ? 0 : (arrayMax(geometry.groupBuffer.ref.value) + 1)
case 'direct-volume':
return 1
case 'isosurface':
return geometry.groupCount.ref.value
}
}
......@@ -88,6 +94,7 @@ export namespace Geometry {
case 'text': return Text.Utils as any
case 'lines': return Lines.Utils as any
case 'direct-volume': return DirectVolume.Utils as any
case 'isosurface': return Isosurface.Utils as any
}
throw new Error('unknown geometry kind')
}
......
/**
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { ValueCell } from 'mol-util'
import { Sphere3D } from 'mol-math/geometry'
import { ParamDefinition as PD } from 'mol-util/param-definition';
import { LocationIterator } from 'mol-geo/util/location-iterator';
import { TransformData } from '../transform-data';
import { createColors } from '../color-data';
import { createMarkers } from '../marker-data';
import { GeometryUtils } from '../geometry';
import { Theme } from 'mol-theme/theme';
import { Color } from 'mol-util/color';
import { BaseGeometry } from '../base';
import { createEmptyOverpaint } from '../overpaint-data';
import { createEmptyTransparency } from '../transparency-data';
import { IsosurfaceValues } from 'mol-gl/renderable/isosurface';
import { calculateTransformBoundingSphere } from 'mol-gl/renderable/util';
import { Texture } from 'mol-gl/webgl/texture';
import { Vec2 } from 'mol-math/linear-algebra';
import { fillSerial } from 'mol-util/array';
export interface Isosurface {
readonly kind: 'isosurface',
/** Number of vertices in the isosurface */
readonly vertexCount: ValueCell<number>,
/** Number of groups in the isosurface */
readonly groupCount: ValueCell<number>,
readonly vertexTexture: ValueCell<Texture>,
readonly vertexTextureDim: ValueCell<Vec2>,
/** Normal buffer as array of xyz values for each vertex wrapped in a value cell */
readonly normalBuffer: ValueCell<Float32Array>,
/** Group buffer as array of group ids for each vertex wrapped in a value cell */
readonly groupBuffer: ValueCell<Float32Array>,
readonly boundingSphere: ValueCell<Sphere3D>,
}
export namespace Isosurface {
export function create(vertexCount: number, groupCount: number, vertexTexture: Texture, normalBuffer: Float32Array, groupBuffer: Float32Array, boundingSphere: Sphere3D, isosurface?: Isosurface): Isosurface {
const { width, height } = vertexTexture
if (isosurface) {
ValueCell.update(isosurface.vertexCount, vertexCount)
ValueCell.update(isosurface.groupCount, groupCount)
ValueCell.update(isosurface.vertexTexture, vertexTexture)
ValueCell.update(isosurface.vertexTextureDim, Vec2.set(isosurface.vertexTextureDim.ref.value, width, height))
ValueCell.update(isosurface.normalBuffer, normalBuffer)
ValueCell.update(isosurface.groupBuffer, groupBuffer)
ValueCell.update(isosurface.boundingSphere, boundingSphere)
return isosurface
} else {
return {
kind: 'isosurface',
vertexCount: ValueCell.create(vertexCount),
groupCount: ValueCell.create(groupCount),
vertexTexture: ValueCell.create(vertexTexture),
vertexTextureDim: ValueCell.create(Vec2.create(width, height)),
normalBuffer: ValueCell.create(normalBuffer),
groupBuffer: ValueCell.create(groupBuffer),
boundingSphere: ValueCell.create(boundingSphere),
}
}
}
export function createEmpty(isosurface?: Isosurface): Isosurface {
return {} as Isosurface // TODO
}
export const Params = {
...BaseGeometry.Params,
doubleSided: PD.Boolean(false),
flipSided: PD.Boolean(false),
flatShaded: PD.Boolean(false),
}
export type Params = typeof Params
export const Utils: GeometryUtils<Isosurface, Params> = {
Params,
createEmpty,
createValues,
createValuesSimple,
updateValues,
updateBoundingSphere,
createRenderableState: BaseGeometry.createRenderableState,
updateRenderableState: BaseGeometry.updateRenderableState
}
function createValues(isosurface: Isosurface, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: PD.Values<Params>): IsosurfaceValues {
const { instanceCount, groupCount } = locationIt
const color = createColors(locationIt, theme.color)
const marker = createMarkers(instanceCount * groupCount)
const overpaint = createEmptyOverpaint()
const transparency = createEmptyTransparency()
const counts = { drawCount: isosurface.vertexCount.ref.value, groupCount, instanceCount }
const transformBoundingSphere = calculateTransformBoundingSphere(isosurface.boundingSphere.ref.value, transform.aTransform.ref.value, transform.instanceCount.ref.value)
return {
tPosition: isosurface.vertexTexture,
uPositionTexDim: isosurface.vertexTextureDim,
aIndex: ValueCell.create(fillSerial(new Float32Array(isosurface.vertexCount.ref.value))),
aNormal: isosurface.normalBuffer,
aGroup: isosurface.groupBuffer,
boundingSphere: ValueCell.create(transformBoundingSphere),
invariantBoundingSphere: isosurface.boundingSphere,
...color,
...marker,
...overpaint,
...transparency,
...transform,
...BaseGeometry.createValues(props, counts),
dDoubleSided: ValueCell.create(props.doubleSided),
dFlatShaded: ValueCell.create(props.flatShaded),
dFlipSided: ValueCell.create(props.flipSided),
dPositionTexture: ValueCell.create(true),
}
}
function createValuesSimple(isosurface: Isosurface, props: Partial<PD.Values<Params>>, colorValue: Color, sizeValue: number, transform?: TransformData) {
const s = BaseGeometry.createSimple(colorValue, sizeValue, transform)
const p = { ...PD.getDefaultValues(Params), ...props }
return createValues(isosurface, s.transform, s.locationIterator, s.theme, p)
}
function updateValues(values: IsosurfaceValues, props: PD.Values<Params>) {
if (Color.fromNormalizedArray(values.uHighlightColor.ref.value, 0) !== props.highlightColor) {
ValueCell.update(values.uHighlightColor, Color.toArrayNormalized(props.highlightColor, values.uHighlightColor.ref.value, 0))
}
if (Color.fromNormalizedArray(values.uSelectColor.ref.value, 0) !== props.selectColor) {
ValueCell.update(values.uSelectColor, Color.toArrayNormalized(props.selectColor, values.uSelectColor.ref.value, 0))
}
ValueCell.updateIfChanged(values.alpha, props.alpha) // `uAlpha` is set in renderable.render
ValueCell.updateIfChanged(values.dUseFog, props.useFog)
ValueCell.updateIfChanged(values.dDoubleSided, props.doubleSided)
ValueCell.updateIfChanged(values.dFlatShaded, props.flatShaded)
ValueCell.updateIfChanged(values.dFlipSided, props.flipSided)
}
function updateBoundingSphere(values: IsosurfaceValues, isosurface: Isosurface) {
const invariantBoundingSphere = isosurface.boundingSphere.ref.value
const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, values.aTransform.ref.value, values.instanceCount.ref.value)
if (!Sphere3D.equals(boundingSphere, values.boundingSphere.ref.value)) {
ValueCell.update(values.boundingSphere, boundingSphere)
}
if (!Sphere3D.equals(invariantBoundingSphere, values.invariantBoundingSphere.ref.value)) {
ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere)
}
}
}
\ No newline at end of file
......@@ -14,6 +14,7 @@ import { PointsValues, PointsRenderable } from './renderable/points';
import { LinesValues, LinesRenderable } from './renderable/lines';
import { SpheresValues, SpheresRenderable } from './renderable/spheres';
import { TextValues, TextRenderable } from './renderable/text';
import { IsosurfaceValues, IsosurfaceRenderable } from './renderable/isosurface';
const getNextId = idFactory(0, 0x7FFFFFFF)
......@@ -26,10 +27,11 @@ export interface SpheresRenderObject extends BaseRenderObject { type: 'spheres',
export interface TextRenderObject extends BaseRenderObject { type: 'text', values: TextValues }
export interface LinesRenderObject extends BaseRenderObject { type: 'lines', values: LinesValues }
export interface DirectVolumeRenderObject extends BaseRenderObject { type: 'direct-volume', values: DirectVolumeValues }
export interface IsosurfaceRenderObject extends BaseRenderObject { type: 'isosurface', values: IsosurfaceValues }
//
export type GraphicsRenderObject = MeshRenderObject | PointsRenderObject | SpheresRenderObject | TextRenderObject | LinesRenderObject | DirectVolumeRenderObject
export type GraphicsRenderObject = MeshRenderObject | PointsRenderObject | SpheresRenderObject | TextRenderObject | LinesRenderObject | DirectVolumeRenderObject | IsosurfaceRenderObject
export type RenderObjectKindType = {
'mesh': MeshRenderObject
......@@ -38,6 +40,7 @@ export type RenderObjectKindType = {
'text': TextRenderObject
'lines': LinesRenderObject
'direct-volume': DirectVolumeRenderObject
'isosurface': IsosurfaceRenderObject
}
export type RenderObjectValuesType = {
'mesh': MeshValues
......@@ -46,6 +49,7 @@ export type RenderObjectValuesType = {
'text': TextValues
'lines': LinesValues
'direct-volume': DirectVolumeValues
'isosurface': IsosurfaceValues
}
export type RenderObjectType = keyof RenderObjectKindType
......@@ -63,5 +67,6 @@ export function createRenderable(ctx: WebGLContext, o: GraphicsRenderObject): Re
case 'text': return TextRenderable(ctx, o.id, o.values, o.state, o.materialId)
case 'lines': return LinesRenderable(ctx, o.id, o.values, o.state, o.materialId)
case 'direct-volume': return DirectVolumeRenderable(ctx, o.id, o.values, o.state, o.materialId)
case 'isosurface': return IsosurfaceRenderable(ctx, o.id, o.values, o.state, o.materialId)
}
}
\ No newline at end of file
/**
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { Renderable, RenderableState, createRenderable } from '../renderable'
import { WebGLContext } from '../webgl/context';
import { createGraphicsRenderItem } from '../webgl/render-item';
import { GlobalUniformSchema, BaseSchema, AttributeSpec, DefineSpec, Values, InternalSchema, InternalValues, UniformSpec, TextureSpec } from './schema';
import { MeshShaderCode } from '../shader-code';
import { ValueCell } from 'mol-util';
export const IsosurfaceSchema = {
...BaseSchema,
aIndex: AttributeSpec('float32', 1, 0),
aNormal: AttributeSpec('float32', 3, 0),
uPositionTexDim: UniformSpec('v2'),
tPosition: TextureSpec('texture', 'rgba', 'float', 'nearest'),
dFlatShaded: DefineSpec('boolean'),
dDoubleSided: DefineSpec('boolean'),
dFlipSided: DefineSpec('boolean'),
dPositionTexture: DefineSpec('boolean'),
}
export type IsosurfaceSchema = typeof IsosurfaceSchema
export type IsosurfaceValues = Values<IsosurfaceSchema>
export function IsosurfaceRenderable(ctx: WebGLContext, id: number, values: IsosurfaceValues, state: RenderableState, materialId: number): Renderable<IsosurfaceValues> {
const schema = { ...GlobalUniformSchema, ...InternalSchema, ...IsosurfaceSchema }
const internalValues: InternalValues = {
uObjectId: ValueCell.create(id),
uPickable: ValueCell.create(state.pickable ? 1 : 0)
}
const shaderCode = MeshShaderCode
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId)
return createRenderable(renderItem, values, state)
}
\ No newline at end of file
mat4 modelView = uView * uModel * aTransform;
vec4 mvPosition = modelView * vec4(aPosition, 1.0);
#ifdef dPositionTexture
vec3 position = readFromTexture(tPosition, aIndex, uPositionTexDim).xyz;
#else
vec3 position = aPosition;
#endif
vec4 mvPosition = modelView * vec4(position, 1.0);
vViewPosition = mvPosition.xyz;
gl_Position = uProjection * mvPosition;
\ No newline at end of file
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
......@@ -10,7 +10,13 @@ precision highp int;
#pragma glslify: import('./chunks/common-vert-params.glsl')
#pragma glslify: import('./chunks/color-vert-params.glsl')
attribute vec3 aPosition;
#ifdef dPositionTexture
attribute float aIndex;
uniform vec2 uPositionTexDim;
uniform sampler2D tPosition;
#else
attribute vec3 aPosition;
#endif
attribute mat4 aTransform;
attribute float aInstance;
attribute float aGroup;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment