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

renderable refactoring

parent a025d5ba
Branches
Tags
No related merge requests found
......@@ -4,7 +4,7 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { createRenderObject, RenderObject, getNextMaterialId } from 'mol-gl/render-object'
import { createRenderObject, GraphicsRenderObject, getNextMaterialId } from 'mol-gl/render-object'
import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder';
import { addSphere } from 'mol-geo/geometry/mesh/builder/sphere';
import { Mesh } from 'mol-geo/geometry/mesh/mesh';
......@@ -27,15 +27,15 @@ export const DebugHelperParams = {
export type DebugHelperParams = typeof DebugHelperParams
export type DebugHelperProps = PD.Values<DebugHelperParams>
type BoundingSphereData = { boundingSphere: Sphere3D, renderObject: RenderObject, mesh: Mesh }
type BoundingSphereData = { boundingSphere: Sphere3D, renderObject: GraphicsRenderObject, mesh: Mesh }
export class BoundingSphereHelper {
readonly scene: Scene
private readonly parent: Scene
private _props: DebugHelperProps
private objectsData = new Map<RenderObject, BoundingSphereData>()
private instancesData = new Map<RenderObject, BoundingSphereData>()
private objectsData = new Map<GraphicsRenderObject, BoundingSphereData>()
private instancesData = new Map<GraphicsRenderObject, BoundingSphereData>()
private sceneData: BoundingSphereData | undefined
constructor(ctx: WebGLContext, parent: Scene, props: Partial<DebugHelperProps>) {
......
......@@ -8,7 +8,6 @@ import { RenderableState, Renderable } from './renderable'
import { RenderableValues } from './renderable/schema';
import { idFactory } from 'mol-util/id-factory';
import { WebGLContext } from './webgl/context';
import { GaussianDensityValues, GaussianDensityRenderable } from './renderable/gaussian-density';
import { DirectVolumeValues, DirectVolumeRenderable } from './renderable/direct-volume';
import { MeshValues, MeshRenderable } from './renderable/mesh';
import { PointsValues, PointsRenderable } from './renderable/points';
......@@ -28,16 +27,10 @@ export interface TextRenderObject extends BaseRenderObject { type: 'text', value
export interface LinesRenderObject extends BaseRenderObject { type: 'lines', values: LinesValues }
export interface DirectVolumeRenderObject extends BaseRenderObject { type: 'direct-volume', values: DirectVolumeValues }
export interface GaussianDensityRenderObject extends BaseRenderObject { type: 'gaussian-density', values: GaussianDensityValues }
//
export type GraphicsRenderObject = MeshRenderObject | PointsRenderObject | SpheresRenderObject | TextRenderObject | LinesRenderObject | DirectVolumeRenderObject
export type ComputeRenderObject = GaussianDensityRenderObject
export type RenderObject = GraphicsRenderObject | ComputeRenderObject
export type RenderObjectKindType = {
'mesh': MeshRenderObject
'points': PointsRenderObject
......@@ -45,8 +38,6 @@ export type RenderObjectKindType = {
'text': TextRenderObject
'lines': LinesRenderObject
'direct-volume': DirectVolumeRenderObject
'gaussian-density': GaussianDensityRenderObject
}
export type RenderObjectValuesType = {
'mesh': MeshValues
......@@ -55,8 +46,6 @@ export type RenderObjectValuesType = {
'text': TextValues
'lines': LinesValues
'direct-volume': DirectVolumeValues
'gaussian-density': GaussianDensityValues
}
export type RenderObjectType = keyof RenderObjectKindType
......@@ -66,7 +55,7 @@ export function createRenderObject<T extends RenderObjectType>(type: T, values:
return { id: getNextId(), type, values, state, materialId } as RenderObjectKindType[T]
}
export function createRenderable(ctx: WebGLContext, o: RenderObject): Renderable<any> {
export function createRenderable(ctx: WebGLContext, o: GraphicsRenderObject): Renderable<any> {
switch (o.type) {
case 'mesh': return MeshRenderable(ctx, o.id, o.values, o.state, o.materialId)
case 'points': return PointsRenderable(ctx, o.id, o.values, o.state, o.materialId)
......@@ -74,7 +63,5 @@ export function createRenderable(ctx: WebGLContext, o: RenderObject): Renderable
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 'gaussian-density': return GaussianDensityRenderable(ctx, o.id, o.values, o.state)
}
}
\ No newline at end of file
......@@ -51,3 +51,27 @@ export function createRenderable<T extends Values<RenderableSchema>>(renderItem:
dispose: () => renderItem.destroy()
}
}
//
export interface ComputeRenderable<T extends RenderableValues> {
readonly id: number
readonly values: T
render: () => void
getProgram: () => Program
update: () => void
dispose: () => void
}
export function createComputeRenderable<T extends Values<RenderableSchema>>(renderItem: RenderItem, values: T): ComputeRenderable<T> {
return {
id: getNextRenderableId(),
values,
render: () => renderItem.render('draw'),
getProgram: () => renderItem.getProgram('draw'),
update: () => renderItem.update(),
dispose: () => renderItem.destroy()
}
}
\ No newline at end of file
......@@ -7,7 +7,7 @@
import { Renderable } from './renderable'
import { WebGLContext } from './webgl/context';
import { RenderableValues, BaseValues } from './renderable/schema';
import { RenderObject, createRenderable, GraphicsRenderObject } from './render-object';
import { GraphicsRenderObject, createRenderable } from './render-object';
import { Object3D } from './object3d';
import { Sphere3D } from 'mol-math/geometry';
import { Vec3 } from 'mol-math/linear-algebra';
......@@ -58,16 +58,16 @@ interface Scene extends Object3D {
readonly boundingSphere: Sphere3D
update: (objects: ArrayLike<GraphicsRenderObject> | undefined, keepBoundingSphere: boolean) => void
add: (o: RenderObject) => Renderable<any>
remove: (o: RenderObject) => void
has: (o: RenderObject) => boolean
add: (o: GraphicsRenderObject) => Renderable<any>
remove: (o: GraphicsRenderObject) => void
has: (o: GraphicsRenderObject) => boolean
clear: () => void
forEach: (callbackFn: (value: Renderable<RenderableValues & BaseValues>, key: RenderObject) => void) => void
forEach: (callbackFn: (value: Renderable<RenderableValues & BaseValues>, key: GraphicsRenderObject) => void) => void
}
namespace Scene {
export function create(ctx: WebGLContext): Scene {
const renderableMap = new Map<RenderObject, Renderable<RenderableValues & BaseValues>>()
const renderableMap = new Map<GraphicsRenderObject, Renderable<RenderableValues & BaseValues>>()
const renderables: Renderable<RenderableValues & BaseValues>[] = []
const boundingSphere = Sphere3D.zero()
let boundingSphereDirty = true
......@@ -95,7 +95,7 @@ namespace Scene {
}
if (!keepBoundingSphere) boundingSphereDirty = true
},
add: (o: RenderObject) => {
add: (o: GraphicsRenderObject) => {
if (!renderableMap.has(o)) {
const renderable = createRenderable(ctx, o)
renderables.push(renderable)
......@@ -108,7 +108,7 @@ namespace Scene {
return renderableMap.get(o)!
}
},
remove: (o: RenderObject) => {
remove: (o: GraphicsRenderObject) => {
const renderable = renderableMap.get(o)
if (renderable) {
renderable.dispose()
......@@ -118,7 +118,7 @@ namespace Scene {
boundingSphereDirty = true
}
},
has: (o: RenderObject) => {
has: (o: GraphicsRenderObject) => {
return renderableMap.has(o)
},
clear: () => {
......@@ -129,7 +129,7 @@ namespace Scene {
renderableMap.clear()
boundingSphereDirty = true
},
forEach: (callbackFn: (value: Renderable<any>, key: RenderObject) => void) => {
forEach: (callbackFn: (value: Renderable<any>, key: GraphicsRenderObject) => void) => {
renderableMap.forEach(callbackFn)
},
get count() {
......
......@@ -60,12 +60,6 @@ export const MeshShaderCode = ShaderCode(
{ standardDerivatives: true, fragDepth: false }
)
export const GaussianDensityShaderCode = ShaderCode(
require('mol-gl/shader/gaussian-density.vert'),
require('mol-gl/shader/gaussian-density.frag'),
{ standardDerivatives: false, fragDepth: false }
)
export const DirectVolumeShaderCode = ShaderCode(
require('mol-gl/shader/direct-volume.vert'),
require('mol-gl/shader/direct-volume.frag'),
......
/**
* Copyright (c) 2017-2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2017-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Michael Krone <michael.krone@uni-tuebingen.de>
......@@ -11,17 +11,47 @@ import { Box3D } from '../../geometry'
import { GaussianDensityGPUProps, getDelta } from '../gaussian-density'
import { OrderedSet } from 'mol-data/int'
import { Vec3, Tensor, Mat4 } from '../../linear-algebra'
import { GaussianDensityValues } from 'mol-gl/renderable/gaussian-density'
import { ValueCell } from 'mol-util'
import { RenderableState, Renderable } from 'mol-gl/renderable'
import { createRenderable, createRenderObject } from 'mol-gl/render-object'
import { createComputeRenderable, ComputeRenderable } from 'mol-gl/renderable'
import { WebGLContext } from 'mol-gl/webgl/context';
import { createTexture, Texture } from 'mol-gl/webgl/texture';
import { GLRenderingContext } from 'mol-gl/webgl/compat';
import { decodeFloatRGB } from 'mol-util/float-packing';
import { ShaderCode } from 'mol-gl/shader-code';
import { createRenderItem } from 'mol-gl/webgl/render-item';
import { ValueSpec, AttributeSpec, UniformSpec, TextureSpec, DefineSpec, Values } from 'mol-gl/renderable/schema';
export const GaussianDensitySchema = {
drawCount: ValueSpec('number'),
instanceCount: ValueSpec('number'),
aRadius: AttributeSpec('float32', 1, 0),
aPosition: AttributeSpec('float32', 3, 0),
aGroup: AttributeSpec('float32', 1, 0),
uCurrentSlice: UniformSpec('f'),
uCurrentX: UniformSpec('f'),
uCurrentY: UniformSpec('f'),
uBboxMin: UniformSpec('v3'),
uBboxMax: UniformSpec('v3'),
uBboxSize: UniformSpec('v3'),
uGridDim: UniformSpec('v3'),
uGridTexDim: UniformSpec('v3'),
uAlpha: UniformSpec('f'),
tMinDistanceTex: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
dGridTexType: DefineSpec('string', ['2d', '3d']),
dCalcType: DefineSpec('string', ['density', 'minDistance', 'groupId']),
}
export const GaussianDensityShaderCode = ShaderCode(
require('mol-gl/shader/gaussian-density.vert'),
require('mol-gl/shader/gaussian-density.frag'),
{ standardDerivatives: false, fragDepth: false }
)
/** name for shared framebuffer used for gpu gaussian surface operations */
const FramebufferName = 'gaussian-density-gpu'
const FramebufferName = 'gaussian-density'
export async function GaussianDensityGPU(ctx: RuntimeContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, webgl: WebGLContext): Promise<DensityData> {
// always use texture2d when the gaussian density needs to be downloaded from the GPU,
......@@ -64,13 +94,12 @@ async function GaussianDensityTexture2d(ctx: RuntimeContext, webgl: WebGLContext
const minDistanceTexture = createTexture(webgl, 'image-uint8', 'rgba', 'ubyte', 'nearest')
minDistanceTexture.define(texDimX, texDimY)
const renderObject = getGaussianDensityRenderObject(webgl, drawCount, positions, radii, groups, minDistanceTexture, expandedBox, dim, smoothness)
const renderable = createRenderable(webgl, renderObject)
const renderable = getGaussianDensityRenderable(webgl, drawCount, positions, radii, groups, minDistanceTexture, expandedBox, dim, smoothness)
//
const { gl, framebufferCache } = webgl
const { uCurrentSlice, uCurrentX, uCurrentY } = renderObject.values
const { uCurrentSlice, uCurrentX, uCurrentY } = renderable.values
const framebuffer = framebufferCache.get(webgl, FramebufferName).value
framebuffer.bind()
......@@ -94,7 +123,7 @@ async function GaussianDensityTexture2d(ctx: RuntimeContext, webgl: WebGLContext
ValueCell.update(uCurrentSlice, i)
ValueCell.update(uCurrentX, currX)
ValueCell.update(uCurrentY, currY)
renderable.render('draw')
renderable.render()
++currCol
currX += dx
}
......@@ -123,13 +152,12 @@ async function GaussianDensityTexture3d(ctx: RuntimeContext, webgl: WebGLContext
const minDistanceTexture = createTexture(webgl, 'volume-uint8', 'rgba', 'ubyte', 'nearest')
minDistanceTexture.define(dx, dy, dz)
const renderObject = getGaussianDensityRenderObject(webgl, drawCount, positions, radii, groups, minDistanceTexture, expandedBox, dim, smoothness)
const renderable = createRenderable(webgl, renderObject)
const renderable = getGaussianDensityRenderable(webgl, drawCount, positions, radii, groups, minDistanceTexture, expandedBox, dim, smoothness)
//
const { gl, framebufferCache } = webgl
const { uCurrentSlice } = renderObject.values
const { uCurrentSlice } = renderable.values
const framebuffer = framebufferCache.get(webgl, FramebufferName).value
framebuffer.bind()
......@@ -143,7 +171,7 @@ async function GaussianDensityTexture3d(ctx: RuntimeContext, webgl: WebGLContext
for (let i = 0; i < dz; ++i) {
ValueCell.update(uCurrentSlice, i)
fbTex.attachFramebuffer(framebuffer, 0, i)
renderable.render('draw')
renderable.render()
}
}
......@@ -204,11 +232,11 @@ async function prepareGaussianDensityData(ctx: RuntimeContext, position: Positio
return { drawCount: n, positions, radii, groups, delta, expandedBox, dim }
}
function getGaussianDensityRenderObject(webgl: WebGLContext, drawCount: number, positions: Float32Array, radii: Float32Array, groups: Float32Array, minDistanceTexture: Texture, box: Box3D, dimensions: Vec3, smoothness: number) {
function getGaussianDensityRenderable(webgl: WebGLContext, drawCount: number, positions: Float32Array, radii: Float32Array, groups: Float32Array, minDistanceTexture: Texture, box: Box3D, dimensions: Vec3, smoothness: number) {
const extent = Vec3.sub(Vec3.zero(), box.max, box.min)
const { texDimX, texDimY } = getTexture2dSize(webgl.maxTextureSize, dimensions)
const values: GaussianDensityValues = {
const values: Values<typeof GaussianDensitySchema> = {
drawCount: ValueCell.create(drawCount),
instanceCount: ValueCell.create(1),
......@@ -230,16 +258,12 @@ function getGaussianDensityRenderObject(webgl: WebGLContext, drawCount: number,
dGridTexType: ValueCell.create(minDistanceTexture.depth > 0 ? '3d' : '2d'),
dCalcType: ValueCell.create('density'),
}
const state: RenderableState = {
visible: true,
alphaFactor: 1,
pickable: false,
opaque: true
}
const renderObject = createRenderObject('gaussian-density', values, state, -1)
const schema = { ...GaussianDensitySchema }
const shaderCode = GaussianDensityShaderCode
const renderItem = createRenderItem(webgl, 'points', shaderCode, schema, values, -1)
return renderObject
return createComputeRenderable(renderItem, values)
}
function setRenderingDefaults(gl: GLRenderingContext) {
......@@ -249,30 +273,30 @@ function setRenderingDefaults(gl: GLRenderingContext) {
gl.enable(gl.BLEND)
}
function setupMinDistanceRendering(webgl: WebGLContext, renderable: Renderable<any>) {
function setupMinDistanceRendering(webgl: WebGLContext, renderable: ComputeRenderable<any>) {
const { gl } = webgl
ValueCell.update(renderable.values.dCalcType, 'minDistance')
renderable.update()
renderable.getProgram('draw').use()
renderable.getProgram().use()
gl.blendFunc(gl.ONE, gl.ONE)
// the shader writes 1 - dist so we set blending to MAX
gl.blendEquation(webgl.extensions.blendMinMax.MAX)
}
function setupDensityRendering(webgl: WebGLContext, renderable: Renderable<any>) {
function setupDensityRendering(webgl: WebGLContext, renderable: ComputeRenderable<any>) {
const { gl } = webgl
ValueCell.update(renderable.values.dCalcType, 'density')
renderable.update()
renderable.getProgram('draw').use()
renderable.getProgram().use()
gl.blendFunc(gl.ONE, gl.ONE)
gl.blendEquation(gl.FUNC_ADD)
}
function setupGroupIdRendering(webgl: WebGLContext, renderable: Renderable<any>) {
function setupGroupIdRendering(webgl: WebGLContext, renderable: ComputeRenderable<any>) {
const { gl } = webgl
ValueCell.update(renderable.values.dCalcType, 'groupId')
renderable.update()
renderable.getProgram('draw').use()
renderable.getProgram().use()
// overwrite color, don't change alpha
gl.blendFuncSeparate(gl.ONE, gl.ZERO, gl.ZERO, gl.ONE)
gl.blendEquation(gl.FUNC_ADD)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment