diff --git a/src/apps/render-test/state.ts b/src/apps/render-test/state.ts index b262e21353b61941748cfc4c08c4ff9015ecfb10..b5923215a789b9f548b5989fefb24f4b11b6d15c 100644 --- a/src/apps/render-test/state.ts +++ b/src/apps/render-test/state.ts @@ -47,13 +47,16 @@ export default class State { const structures = await getStructuresFromPdbId(pdbId) const struct = await Run(Symmetry.buildAssembly(structures[0], '1')) - // const structPointRepr = StructureRepresentation(Point) - // await Run(structPointRepr.create(struct)) - // structPointRepr.renderObjects.forEach(viewer.add) + const structPointRepr = StructureRepresentation(Point) + await Run(structPointRepr.create(struct)) + structPointRepr.renderObjects.forEach(viewer.add) - const structSpacefillRepr = StructureRepresentation(Spacefill) - await Run(structSpacefillRepr.create(struct, { detail: 0 })) - structSpacefillRepr.renderObjects.forEach(viewer.add) + // const structSpacefillRepr = StructureRepresentation(Spacefill) + // await Run(structSpacefillRepr.create(struct, { detail: 0 })) + // structSpacefillRepr.renderObjects.forEach(viewer.add) + + viewer.requestDraw() + console.log(viewer.stats) this.loading.next(false) } diff --git a/src/mol-geo/color/data.ts b/src/mol-geo/color/data.ts index 03302f011316d52e5f43a2c4b1ed831aad48b77a..71c820850271283fef7cb96818423a46f3d0cb4d 100644 --- a/src/mol-geo/color/data.ts +++ b/src/mol-geo/color/data.ts @@ -5,31 +5,10 @@ */ import { ValueCell } from 'mol-util'; +import { ColorTexture, createColorTexture } from 'mol-gl/renderable/util'; import Color from './color'; import { Mesh } from '../shape/mesh'; -function calculateTextureInfo (n: number, itemSize: number) { - const sqN = Math.sqrt(n * itemSize) - let width = Math.ceil(sqN) - width = width + (itemSize - (width % itemSize)) % itemSize - const height = width > 0 ? Math.ceil(n * itemSize / width) : 0 - return { width, height, length: width * height * itemSize } -} - -interface ColorTexture extends Uint8Array { - width: number, - height: number -} - -function createColorTexture (n: number): ColorTexture { - const colorTexInfo = calculateTextureInfo(n, 3) - const colorTexture = new Uint8Array(colorTexInfo.length) - return Object.assign(colorTexture, { - width: colorTexInfo.width, - height: colorTexInfo.height - }) -} - export type UniformColor = { type: 'uniform', value: number[] } export type AttributeColor = { type: 'attribute', value: ValueCell<Float32Array> } export type InstanceColor = { type: 'instance', value: ValueCell<ColorTexture> } diff --git a/src/mol-geo/color/scale.ts b/src/mol-geo/color/scale.ts index 5673e1c94f35aaa92094e03c9ee6bbcc89846df4..fd171d26c584d6cf637eb1e55c0440ada61a7e46 100644 --- a/src/mol-geo/color/scale.ts +++ b/src/mol-geo/color/scale.ts @@ -28,9 +28,10 @@ export namespace ColorScale { const { domain, reverse, colors } = { ...DefaultColorScale, ...props } const [ min, max ] = reverse ? domain.slice().reverse() : domain const count1 = colors.length - 1 + const diff = (max - min) || 1 function color(value: number) { - const t = ((value - min) / (max - min)) * count1 + const t = ((value - min) / diff) * count1 const tf = Math.floor(t) const c1 = colors[tf] const c2 = colors[Math.ceil(t)] diff --git a/src/mol-geo/representation/structure/point.ts b/src/mol-geo/representation/structure/point.ts index 2c3143cb79c854591e6bb2d70bafbeed93f01986..64b2ab7029b1fc0aa411f83d0124935fe28e9e6a 100644 --- a/src/mol-geo/representation/structure/point.ts +++ b/src/mol-geo/representation/structure/point.ts @@ -6,8 +6,7 @@ import { ValueCell } from 'mol-util/value-cell' -import { createRenderObject, RenderObject } from 'mol-gl/scene' -import { createColorTexture } from 'mol-gl/util'; +import { createPointRenderObject, RenderObject } from 'mol-gl/scene' import { Mat4 } from 'mol-math/linear-algebra' import { OrderedSet } from 'mol-data/int' import { ChunkedArray } from 'mol-data/util'; @@ -15,6 +14,9 @@ import { Unit, ElementGroup } from 'mol-model/structure'; import { RepresentationProps, UnitsRepresentation } from './index'; import { Task } from 'mol-task' import { VdwRadius } from 'mol-model/structure/model/properties/atomic'; +import { createUniformColor, createInstanceColor } from '../../color/data'; +import { fillSerial } from 'mol-gl/renderable/util'; +import { ColorScale } from '../../color/scale'; export const DefaultPointProps = { @@ -39,29 +41,37 @@ export default function Point(): UnitsRepresentation<PointProps> { ChunkedArray.add3(vertices, x[e], y[e], z[e]) ChunkedArray.add(sizes, VdwRadius(type_symbol.value(e))) - if (i % 10 === 0 && ctx.shouldUpdate) { + if (i % 10000 === 0 && ctx.shouldUpdate) { await ctx.update({ message: 'Point', current: i, max: elementCount }); } } - const unitsCount = units.length - const transformArray = new Float32Array(unitsCount * 16) - for (let i = 0; i < unitsCount; i++) { + const unitCount = units.length + const transformArray = new Float32Array(unitCount * 16) + for (let i = 0; i < unitCount; i++) { Mat4.toArray(units[i].operator.matrix, transformArray, i * 16) } - const color = ValueCell.create(createColorTexture(unitsCount)) - color.ref.value.set([ 0, 0, 255 ]) + // const color = createUniformColor({ value: 0xFF4411 }) + const scale = ColorScale.create({ domain: [ 0, unitCount - 1 ] }) + const color = createInstanceColor({ + colorFn: scale.color, + unitCount + }) + + const points = createPointRenderObject({ + objectId: 0, - const points = createRenderObject('point', { position: ValueCell.create(ChunkedArray.compact(vertices, true) as Float32Array), + id: ValueCell.create(fillSerial(new Float32Array(unitCount))), size: ValueCell.create(ChunkedArray.compact(sizes, true) as Float32Array), color, transform: ValueCell.create(transformArray), - instanceCount: unitsCount, + instanceCount: unitCount, + elementCount, positionCount: vertices.elementCount - }, {}) + }) renderObjects.push(points) }), update: (props: RepresentationProps) => false diff --git a/src/mol-geo/representation/structure/spacefill.ts b/src/mol-geo/representation/structure/spacefill.ts index ae64e3cc0f0763078f5eedf9e87a463caecce893..39c206cf87be50dbcff62dd7565dacd9cd045463 100644 --- a/src/mol-geo/representation/structure/spacefill.ts +++ b/src/mol-geo/representation/structure/spacefill.ts @@ -6,7 +6,7 @@ import { ValueCell } from 'mol-util/value-cell' -import { createRenderObject, RenderObject } from 'mol-gl/scene' +import { RenderObject, createMeshRenderObject } from 'mol-gl/scene' // import { createColorTexture } from 'mol-gl/util'; import { Vec3, Mat4 } from 'mol-math/linear-algebra' import { OrderedSet } from 'mol-data/int' @@ -53,7 +53,7 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> { detail }) - if (i % 10 === 0 && ctx.shouldUpdate) { + if (i % 10000 === 0 && ctx.shouldUpdate) { await ctx.update({ message: 'Spacefill', current: i, max: elementCount }); } } @@ -70,35 +70,31 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> { // console.log({ unitCount, elementCount }) - let colorType = 'element-instance' - let color: ColorData - - if (colorType === 'uniform') { - color = createUniformColor({ value: 0xFF4411 }) - } else if (colorType === 'attribute') { - color = elementSymbolColorData({ units, elementGroup, mesh }) - } else if (colorType === 'instance') { - const scale = ColorScale.create({ domain: [ 0, unitCount - 1 ] }) - color = createInstanceColor({ - colorFn: scale.color, - unitCount - }) - } else if (colorType === 'element-instance') { - const scale = ColorScale.create({ domain: [ 0, unitCount * elementCount - 1 ] }) - color = createElementInstanceColor({ - colorFn: (unitIdx, elementIdx) => scale.color(unitIdx * elementCount + elementIdx), - unitCount, - offsetCount: mesh.offsetCount, - offsets: mesh.offsetBuffer as any - }) - } - console.log(color!) + // const color = createUniformColor({ value: 0xFF4411 }) + + // const color = elementSymbolColorData({ units, elementGroup, mesh }) + + const scale = ColorScale.create({ domain: [ 0, unitCount - 1 ] }) + const color = createInstanceColor({ + colorFn: scale.color, + unitCount + }) + + // const scale = ColorScale.create({ domain: [ 0, unitCount * elementCount - 1 ] }) + // const color = createElementInstanceColor({ + // colorFn: (unitIdx, elementIdx) => scale.color(unitIdx * elementCount + elementIdx), + // unitCount, + // offsetCount: mesh.offsetCount, + // offsets: mesh.offsetBuffer as any + // }) + + const spheres = createMeshRenderObject({ + objectId: 0, - const spheres = createRenderObject('mesh', { position: mesh.vertexBuffer, - normal: mesh.normalBuffer, - color: color!, - id: mesh.idBuffer, + normal: mesh.normalBuffer as ValueCell<Float32Array>, + color: color as ColorData, + id: mesh.idBuffer as ValueCell<Float32Array>, transform: ValueCell.create(transformArray), index: mesh.indexBuffer, @@ -106,7 +102,7 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> { indexCount: mesh.triangleCount, elementCount: mesh.offsetCount - 1, positionCount: mesh.vertexCount - }, {}) + }) renderObjects.push(spheres) }), update: (props: RepresentationProps) => false diff --git a/src/mol-gl/renderable.ts b/src/mol-gl/renderable.ts index 8a7d3f86d9956fc52ddb12edd30c14fd1638d626..273b951e5a6df2230670570327f24f2577b59d41 100644 --- a/src/mol-gl/renderable.ts +++ b/src/mol-gl/renderable.ts @@ -16,6 +16,7 @@ export type AttributesBuffers<T extends AttributesData> = { [K in keyof T]: REGL export interface Renderable { draw(): void + dispose(): void stats: REGL.CommandStats name: string // isPicking: () => boolean diff --git a/src/mol-gl/renderable/mesh.ts b/src/mol-gl/renderable/mesh.ts index 8d74b1032c401108a81c0f444662618f8b2d283d..e58fe1d8b0943a42fcdcc2fdad9ca6b00f15320f 100644 --- a/src/mol-gl/renderable/mesh.ts +++ b/src/mol-gl/renderable/mesh.ts @@ -9,33 +9,20 @@ import { ValueCell } from 'mol-util/value-cell' import { ColorData } from 'mol-geo/color'; import { Renderable } from '../renderable' -import { getBuffers, createTransformAttributes, fillSerial, createColorUniforms } from './util' -import Attribute from '../attribute'; -import { MeshShaders, addDefines, ShaderDefines } from '../shaders' +import { createBaseDefines, createBaseUniforms, createBaseAttributes, destroyAttributes, destroyUniforms } from './util' +import { MeshShaders, addDefines } from '../shaders' type Mesh = 'mesh' -type Uniforms = { [k: string]: REGL.Uniform | REGL.Texture } - -function getColorDefines(color: ColorData) { - const defines: ShaderDefines = {} - switch (color.type) { - case 'uniform': defines.UNIFORM_COLOR = ''; break; - case 'attribute': defines.ATTRIBUTE_COLOR = ''; break; - case 'element': defines.ELEMENT_COLOR = ''; break; - case 'instance': defines.INSTANCE_COLOR = ''; break; - case 'element-instance': defines.ELEMENT_INSTANCE_COLOR = ''; break; - } - return defines -} - namespace Mesh { export type Data = { + objectId: number + position: ValueCell<Float32Array> - normal: ValueCell<Float32Array> + normal?: ValueCell<Float32Array> id: ValueCell<Float32Array> - readonly color: ColorData + color: ColorData transform: ValueCell<Float32Array> index: ValueCell<Uint32Array> @@ -45,42 +32,23 @@ namespace Mesh { positionCount: number } - export function create(regl: REGL.Regl, data: Data, _uniforms: Uniforms): Renderable { - const defines = getColorDefines(data.color) - const instanceId = ValueCell.create(fillSerial(new Float32Array(data.instanceCount))) - const uniforms = { - objectId: _uniforms.objectId || 0, - instanceCount: data.instanceCount, - elementCount: data.elementCount, - ..._uniforms - } - if (data.color.type === 'instance' || data.color.type === 'element' || data.color.type === 'element-instance') { - Object.assign(uniforms, createColorUniforms(regl, data.color.value)) - } else if (data.color.type === 'uniform') { - Object.assign(uniforms, { color: data.color.value }) - } - const attributes = getBuffers({ - instanceId: Attribute.create(regl, instanceId, data.instanceCount, { size: 1, divisor: 1 }), - position: Attribute.create(regl, data.position, data.positionCount, { size: 3 }), - normal: Attribute.create(regl, data.normal, data.positionCount, { size: 3 }), - - elementId: Attribute.create(regl, data.id, data.positionCount, { size: 1 }), - ...createTransformAttributes(regl, data.transform, data.instanceCount) + export function create(regl: REGL.Regl, props: Data): Renderable { + const defines = createBaseDefines(regl, props) + const uniforms = createBaseUniforms(regl, props) + const attributes = createBaseAttributes(regl, props) + const elements = regl.elements({ + data: props.index.ref.value, + primitive: 'triangles', + type: 'uint32', + count: props.indexCount * 3 }) - if (data.color.type === 'attribute') { - attributes.color = Attribute.create(regl, data.color.value, data.positionCount, { size: 3 }).buffer - } + const command = regl({ ...addDefines(defines, MeshShaders), uniforms, attributes, - elements: regl.elements({ - data: data.index.ref.value, - primitive: 'triangles', - type: 'uint32', - count: data.indexCount * 3 - }), - instances: data.instanceCount, + elements, + instances: props.instanceCount, }) return { draw: () => { @@ -89,7 +57,12 @@ namespace Mesh { get stats() { return command.stats }, - name: 'mesh' + name: 'mesh', + dispose: () => { + destroyAttributes(attributes) + destroyUniforms(uniforms) + elements.destroy() + } } } } diff --git a/src/mol-gl/renderable/point.ts b/src/mol-gl/renderable/point.ts index 4d354adbf0d1b82247508f2c331c97ed64a51b12..c18d2d4c56d48cdaabb88f1c54671f8d6fdecc47 100644 --- a/src/mol-gl/renderable/point.ts +++ b/src/mol-gl/renderable/point.ts @@ -8,37 +8,39 @@ import REGL = require('regl'); import { ValueCell } from 'mol-util/value-cell' import { Renderable } from '../renderable' -import { getBuffers, createTransformAttributes, fillSerial } from './util' -import Attribute from '../attribute'; -import { PointShaders } from '../shaders' +import { createBaseDefines, createBaseUniforms, createBaseAttributes, destroyUniforms, destroyAttributes } from './util' +import { PointShaders, addDefines } from '../shaders' +import { ColorData } from 'mol-geo/color'; type Point = 'point' namespace Point { export type Data = { + objectId: number + position: ValueCell<Float32Array> size?: ValueCell<Float32Array> + id: ValueCell<Float32Array> + + color: ColorData transform: ValueCell<Float32Array> instanceCount: number + elementCount: number positionCount: number } - export function create(regl: REGL.Regl, data: Data): Renderable { - const instanceId = ValueCell.create(fillSerial(new Float32Array(data.instanceCount))) - const attributes = getBuffers({ - instanceId: Attribute.create(regl, instanceId, data.instanceCount, { size: 1, divisor: 1 }), - position: Attribute.create(regl, data.position, data.positionCount, { size: 3 }), - ...createTransformAttributes(regl, data.transform, data.positionCount) - }) - if (data.size) { - attributes.size = Attribute.create(regl, data.size, data.positionCount, { size: 1 }).buffer - } + export function create(regl: REGL.Regl, props: Data): Renderable { + const defines = createBaseDefines(regl, props) + const uniforms = createBaseUniforms(regl, props) + const attributes = createBaseAttributes(regl, props) + const command = regl({ - ...PointShaders, + ...addDefines(defines, PointShaders), + uniforms, attributes, - count: data.positionCount, - instances: data.instanceCount, + count: props.positionCount, + instances: props.instanceCount, primitive: 'points' }) return { @@ -46,50 +48,13 @@ namespace Point { get stats() { return command.stats }, - name: 'point' + name: 'point', + dispose: () => { + destroyAttributes(attributes) + destroyUniforms(uniforms) + } } } } -export default Point - -// namespace Point { -// export type DataType = { -// position: { type: Float32Array, itemSize: 3 } -// } -// export type Data = { [K in keyof DataType]: DataType[K]['type'] } -// export type Attributes = { [K in keyof Data]: Attribute<Data[K]> } - -// export function create(regl: REGL.Regl, dataOrCount: Data | number): Renderable<Data> { -// let count: number -// let data: Data -// if (typeof dataOrCount === 'number') { -// count = dataOrCount -// data = { -// position: new Float32Array(count * 3) -// } -// } else { -// count = dataOrCount.position.length / 3 -// data = dataOrCount -// } -// const attributes = createAttributes(regl, data) -// const command = regl({ -// vert: pointVert, -// frag: pointFrag, -// attributes: getBuffers(attributes), -// count, -// primitive: 'points' -// }) -// return { -// draw: () => command(), -// setCount: (newCount: number) => { -// for (const k of Object.keys(data)) { -// attributes[k as keyof Data].setCount(newCount) -// } -// count = newCount -// }, -// getCount: () => count, -// attributes -// } -// } -// } \ No newline at end of file +export default Point \ No newline at end of file diff --git a/src/mol-gl/renderable/util.ts b/src/mol-gl/renderable/util.ts index 8ba334272a9c7232f47e6512b3cecbbefbe97ea8..067c71ec5882a515a8a7edc5a2e4dd12330871dd 100644 --- a/src/mol-gl/renderable/util.ts +++ b/src/mol-gl/renderable/util.ts @@ -7,9 +7,35 @@ import REGL = require('regl'); import { ValueCell } from 'mol-util/value-cell' -import { ColorTexture } from '../util'; import { Attributes, AttributesData, AttributesBuffers } from '../renderable' import Attribute from '../attribute' +import { ColorData } from 'mol-geo/color'; +import { ShaderDefines } from '../shaders'; + +export type ReglUniforms = { [k: string]: REGL.Uniform | REGL.Texture } +export type ReglAttributes = { [k: string]: REGL.AttributeConfig } + +export function calculateTextureInfo (n: number, itemSize: number) { + const sqN = Math.sqrt(n * itemSize) + let width = Math.ceil(sqN) + width = width + (itemSize - (width % itemSize)) % itemSize + const height = width > 0 ? Math.ceil(n * itemSize / width) : 0 + return { width, height, length: width * height * itemSize } +} + +export interface ColorTexture extends Uint8Array { + width: number, + height: number +} + +export function createColorTexture (n: number): ColorTexture { + const colorTexInfo = calculateTextureInfo(n, 3) + const colorTexture = new Uint8Array(colorTexInfo.length) + return Object.assign(colorTexture, { + width: colorTexInfo.width, + height: colorTexInfo.height + }) +} export function createTransformAttributes (regl: REGL.Regl, transform: ValueCell<Float32Array>, count: number) { const size = 4 @@ -40,6 +66,18 @@ export function createColorUniforms (regl: REGL.Regl, color: ValueCell<ColorText } } +export function getColorDefines(color: ColorData) { + const defines: ShaderDefines = {} + switch (color.type) { + case 'uniform': defines.UNIFORM_COLOR = ''; break; + case 'attribute': defines.ATTRIBUTE_COLOR = ''; break; + case 'element': defines.ELEMENT_COLOR = ''; break; + case 'instance': defines.INSTANCE_COLOR = ''; break; + case 'element-instance': defines.ELEMENT_INSTANCE_COLOR = ''; break; + } + return defines +} + export function getBuffers<T extends AttributesData>(attributes: Attributes<T>): AttributesBuffers<T> { const buffers: AttributesBuffers<any> = {} for (const k of Object.keys(attributes)) { @@ -52,4 +90,72 @@ export function fillSerial<T extends Helpers.NumberArray> (array: T) { const n = array.length for (let i = 0; i < n; ++i) array[ i ] = i return array +} + +interface BaseProps { + objectId: number, + instanceCount: number, + elementCount: number, + positionCount: number, + + position: ValueCell<Float32Array> + normal?: ValueCell<Float32Array> + size?: ValueCell<Float32Array> + id: ValueCell<Float32Array> + transform: ValueCell<Float32Array> + color: ColorData +} + +export function createBaseUniforms(regl: REGL.Regl, props: BaseProps): ReglUniforms { + const { objectId, instanceCount, elementCount, color } = props + const uniforms = { objectId, instanceCount, elementCount } + if (color.type === 'instance' || color.type === 'element' || color.type === 'element-instance') { + Object.assign(uniforms, createColorUniforms(regl, color.value)) + } else if (color.type === 'uniform') { + Object.assign(uniforms, { color: color.value }) + } + return uniforms +} + +export function createBaseAttributes(regl: REGL.Regl, props: BaseProps): ReglAttributes { + const { instanceCount, positionCount, position, color, id, normal, size, transform } = props + const instanceId = ValueCell.create(fillSerial(new Float32Array(instanceCount))) + const attributes = getBuffers({ + instanceId: Attribute.create(regl, instanceId, instanceCount, { size: 1, divisor: 1 }), + position: Attribute.create(regl, position, positionCount, { size: 3 }), + elementId: Attribute.create(regl, id, positionCount, { size: 1 }), + ...createTransformAttributes(regl, transform, instanceCount) + }) + if (color.type === 'attribute') { + attributes.color = Attribute.create(regl, color.value, positionCount, { size: 3 }).buffer + } + if (normal) { + attributes.normal = Attribute.create(regl, normal as any, positionCount, { size: 3 }).buffer + } + if (size) { + attributes.size = Attribute.create(regl, size, positionCount, { size: 1 }).buffer + } + return attributes +} + +export function createBaseDefines(regl: REGL.Regl, props: BaseProps) { + return getColorDefines(props.color) +} + +export function destroyAttributes(attributes: ReglAttributes) { + for (const k in attributes) { + const buffer = attributes[k].buffer + if (buffer) { + buffer.destroy() + } + } +} + +export function destroyUniforms(uniforms: ReglUniforms) { + for (const k in uniforms) { + const uniform = uniforms[k] + if ((uniform as any).destroy) { + (uniform as any).destroy() + } + } } \ No newline at end of file diff --git a/src/mol-gl/renderer.ts b/src/mol-gl/renderer.ts index bd925c6f772e47eff9083ab0b07aedd3a8a6a836..9c26eb35ca3eda5140739ce98b7181f88cd5b39f 100644 --- a/src/mol-gl/renderer.ts +++ b/src/mol-gl/renderer.ts @@ -11,6 +11,14 @@ import { Camera } from 'mol-view/camera/base'; import * as glContext from './context' import Scene, { RenderObject } from './scene'; +export interface RendererStats { + elementsCount: number + bufferCount: number + textureCount: number + shaderCount: number + renderableCount: number +} + interface Renderer { add: (o: RenderObject) => void remove: (o: RenderObject) => void @@ -19,6 +27,7 @@ interface Renderer { setViewport: (viewport: Viewport) => void + stats: RendererStats dispose: () => void } @@ -32,7 +41,7 @@ const optionalExtensions = [ namespace Renderer { export function create(canvas: HTMLCanvasElement, camera: Camera): Renderer { - const regl = glContext.create({ canvas, extensions, optionalExtensions, profile: true }) + const regl = glContext.create({ canvas, extensions, optionalExtensions, profile: false }) const scene = Scene.create(regl) const baseContext = regl({ @@ -71,20 +80,26 @@ namespace Renderer { return { add: (o: RenderObject) => { scene.add(o) - draw() }, remove: (o: RenderObject) => { scene.remove(o) - draw() }, clear: () => { scene.clear() - draw() }, draw, setViewport: (viewport: Viewport) => { regl({ viewport }) }, + get stats() { + return { + elementsCount: regl.stats.elementsCount, + bufferCount: regl.stats.bufferCount, + textureCount: regl.stats.textureCount, + shaderCount: regl.stats.shaderCount, + renderableCount: scene.count + } + }, dispose: () => { regl.destroy() } diff --git a/src/mol-gl/scene.ts b/src/mol-gl/scene.ts index c03888827e7ab1e71c814b7f9314fc5ab884e87a..ecc8444c1b9e53dd37aa4537e32cf9a0e1728adf 100644 --- a/src/mol-gl/scene.ts +++ b/src/mol-gl/scene.ts @@ -16,21 +16,21 @@ function getNextId() { export type RenderData = { [k: string]: ValueCell<Helpers.TypedArray> } -export interface RenderObject { - id: number - type: 'mesh' | 'point' - data: PointRenderable.Data | MeshRenderable.Data - uniforms: { [k: string]: REGL.Uniform } -} +export interface MeshRenderObject { id: number, type: 'mesh', props: MeshRenderable.Data } +export interface PointRenderObject { id: number, type: 'point', props: PointRenderable.Data } +export type RenderObject = MeshRenderObject | PointRenderObject -export function createRenderObject(type: 'mesh' | 'point', data: PointRenderable.Data | MeshRenderable.Data, uniforms: { [k: string]: REGL.Uniform }) { - return { id: getNextId(), type, data, uniforms } +export function createMeshRenderObject(props: MeshRenderable.Data): MeshRenderObject { + return { id: getNextId(), type: 'mesh', props } +} +export function createPointRenderObject(props: PointRenderable.Data): PointRenderObject { + return { id: getNextId(), type: 'point', props } } export function createRenderable(regl: REGL.Regl, o: RenderObject) { switch (o.type) { - case 'mesh': return MeshRenderable.create(regl, o.data as MeshRenderable.Data, o.uniforms || {}) - case 'point': return PointRenderable.create(regl, o.data as PointRenderable.Data) + case 'mesh': return MeshRenderable.create(regl, o.props) + case 'point': return PointRenderable.create(regl, o.props) } } @@ -39,6 +39,7 @@ interface Scene { remove: (o: RenderObject) => void clear: () => void forEach: (callbackFn: (value: Renderable) => void) => void + count: number } namespace Scene { @@ -54,21 +55,22 @@ namespace Scene { }, remove: (o: RenderObject) => { if (o.id in objectIdRenderableMap) { - // TODO - // objectIdRenderableMap[o.id].destroy() + objectIdRenderableMap[o.id].dispose() delete objectIdRenderableMap[o.id] } }, clear: () => { for (const id in objectIdRenderableMap) { - // TODO - // objectIdRenderableMap[id].destroy() + objectIdRenderableMap[id].dispose() delete objectIdRenderableMap[id] } renderableList.length = 0 }, forEach: (callbackFn: (value: Renderable) => void) => { renderableList.forEach(callbackFn) + }, + get count() { + return renderableList.length } } } diff --git a/src/mol-gl/shader/chunks/color-assign-material.glsl b/src/mol-gl/shader/chunks/color-assign-material.glsl new file mode 100644 index 0000000000000000000000000000000000000000..321c2afc0f0faf60845b5b91b87cce6e9d1d3532 --- /dev/null +++ b/src/mol-gl/shader/chunks/color-assign-material.glsl @@ -0,0 +1,5 @@ +#if defined(UNIFORM_COLOR) + vec3 material = color; +#elif defined(ATTRIBUTE_COLOR) || defined(INSTANCE_COLOR) || defined(ELEMENT_COLOR) || defined(ELEMENT_INSTANCE_COLOR) + vec3 material = vColor; +#endif \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/color-assign-varying.glsl b/src/mol-gl/shader/chunks/color-assign-varying.glsl new file mode 100644 index 0000000000000000000000000000000000000000..d2feca151fdda6cd85eca9ed0e56a71e35fa89c0 --- /dev/null +++ b/src/mol-gl/shader/chunks/color-assign-varying.glsl @@ -0,0 +1,9 @@ +#if defined(ATTRIBUTE_COLOR) + vColor = color; +#elif defined(INSTANCE_COLOR) + vColor = read_vec3(colorTex, instanceId, colorTexSize); +#elif defined(ELEMENT_COLOR) + vColor = read_vec3(colorTex, elementId, colorTexSize); +#elif defined(ELEMENT_INSTANCE_COLOR) + vColor = read_vec3(colorTex, instanceId * float(elementCount) + elementId, colorTexSize); +#endif \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/color-frag-params.glsl b/src/mol-gl/shader/chunks/color-frag-params.glsl new file mode 100644 index 0000000000000000000000000000000000000000..0acab171a9cecb1f0cb370d5dd562c26fcae0db8 --- /dev/null +++ b/src/mol-gl/shader/chunks/color-frag-params.glsl @@ -0,0 +1,5 @@ +#if defined(UNIFORM_COLOR) + uniform vec3 color; +#elif defined(ATTRIBUTE_COLOR) || defined(INSTANCE_COLOR) || defined(ELEMENT_COLOR) || defined(ELEMENT_INSTANCE_COLOR) + varying vec3 vColor; +#endif \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/color-vert-params.glsl b/src/mol-gl/shader/chunks/color-vert-params.glsl new file mode 100644 index 0000000000000000000000000000000000000000..04a62be6dcb780e8460934cfef16d26b416048f1 --- /dev/null +++ b/src/mol-gl/shader/chunks/color-vert-params.glsl @@ -0,0 +1,12 @@ +#if defined(UNIFORM_COLOR) + uniform vec3 color; +#elif defined(ATTRIBUTE_COLOR) + varying vec3 vColor; + attribute vec3 color; +#elif defined(INSTANCE_COLOR) || defined(ELEMENT_COLOR) || defined(ELEMENT_INSTANCE_COLOR) + varying vec3 vColor; + uniform vec2 colorTexSize; + uniform sampler2D colorTex; +#endif + +#pragma glslify: read_vec3 = require(../utils/read-vec3.glsl) \ No newline at end of file diff --git a/src/mol-gl/shader/mesh.frag b/src/mol-gl/shader/mesh.frag index d7f6d4cafd0b3e15dba88bc296425e8f54c7bc9f..c74254d5bb86e4361dfaf03b2862a42c48e9b78f 100644 --- a/src/mol-gl/shader/mesh.frag +++ b/src/mol-gl/shader/mesh.frag @@ -19,15 +19,11 @@ uniform mat4 view; varying vec3 vNormal, vViewPosition; -#if defined(UNIFORM_COLOR) - uniform vec3 color; -#elif defined(ATTRIBUTE_COLOR) || defined(INSTANCE_COLOR) || defined(ELEMENT_COLOR) || defined(ELEMENT_INSTANCE_COLOR) - varying vec3 vColor; -#endif +#pragma glslify: import('./chunks/color-frag-params.glsl') -#pragma glslify: attenuation = require(./util/attenuation.glsl) -#pragma glslify: calculateSpecular = require(./util/phong-specular.glsl) -#pragma glslify: calculateDiffuse = require(./util/oren-nayar-diffuse.glsl) +#pragma glslify: attenuation = require(./utils/attenuation.glsl) +#pragma glslify: calculateSpecular = require(./utils/phong-specular.glsl) +#pragma glslify: calculateDiffuse = require(./utils/oren-nayar-diffuse.glsl) const float specularScale = 0.65; const float shininess = 100.0; @@ -36,11 +32,7 @@ const float albedo = 0.95; void main() { // material color - #if defined(UNIFORM_COLOR) - vec3 material = color; - #elif defined(ATTRIBUTE_COLOR) || defined(INSTANCE_COLOR) || defined(ELEMENT_COLOR) || defined(ELEMENT_INSTANCE_COLOR) - vec3 material = vColor; - #endif + #pragma glslify: import('./chunks/color-assign-material.glsl') // determine surface to light direction // vec4 lightPosition = view * vec4(light.position, 1.0); diff --git a/src/mol-gl/shader/mesh.vert b/src/mol-gl/shader/mesh.vert index d14e6e058d07b0e2bda7ad764eba628e93ac8302..225a4b878d48f938510f6c20aa271552e66bdb26 100644 --- a/src/mol-gl/shader/mesh.vert +++ b/src/mol-gl/shader/mesh.vert @@ -12,39 +12,23 @@ uniform int objectId; uniform int instanceCount; uniform int elementCount; -#if defined(UNIFORM_COLOR) - uniform vec3 color; -#elif defined(ATTRIBUTE_COLOR) - attribute vec3 color; -#elif defined(INSTANCE_COLOR) || defined(ELEMENT_COLOR) || defined(ELEMENT_INSTANCE_COLOR) - uniform vec2 colorTexSize; - uniform sampler2D colorTex; -#endif +#pragma glslify: import('./chunks/color-vert-params.glsl') attribute vec3 position; -attribute vec3 normal; attribute vec4 transformColumn0, transformColumn1, transformColumn2, transformColumn3; attribute float instanceId; attribute float elementId; -varying vec3 vColor; +attribute vec3 normal; + varying vec3 vNormal; varying vec3 vViewPosition; -#pragma glslify: inverse = require(./util/inverse.glsl) -#pragma glslify: read_vec3 = require(./util/read-vec3.glsl) -#pragma glslify: transpose = require(./util/transpose.glsl) +#pragma glslify: inverse = require(./utils/inverse.glsl) +#pragma glslify: transpose = require(./utils/transpose.glsl) void main(){ - #if defined(ATTRIBUTE_COLOR) - vColor = color; - #elif defined(INSTANCE_COLOR) - vColor = read_vec3(colorTex, instanceId, colorTexSize); - #elif defined(ELEMENT_COLOR) - vColor = read_vec3(colorTex, elementId, colorTexSize); - #elif defined(ELEMENT_INSTANCE_COLOR) - vColor = read_vec3(colorTex, instanceId * float(elementCount) + elementId, colorTexSize); - #endif + #pragma glslify: import('./chunks/color-assign-varying.glsl') mat4 transform = mat4(transformColumn0, transformColumn1, transformColumn2, transformColumn3); mat4 modelView = view * model * transform; diff --git a/src/mol-gl/shader/point.frag b/src/mol-gl/shader/point.frag index 329aedf0a19037ee3f74b0cfc34c924574742cfe..26e6de1bdaa28645ff25e9b8330f1f62b41f2ae9 100644 --- a/src/mol-gl/shader/point.frag +++ b/src/mol-gl/shader/point.frag @@ -4,6 +4,11 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ +precision highp float; + +#pragma glslify: import('./chunks/color-frag-params.glsl') + void main(){ - gl_FragColor = vec4(1, 0, 0, 1); + #pragma glslify: import('./chunks/color-assign-material.glsl') + gl_FragColor = vec4(material, 1); } \ No newline at end of file diff --git a/src/mol-gl/shader/point.vert b/src/mol-gl/shader/point.vert index 86802b5376bf1291f03d411f39fbf5420a0c45bb..080e3b15d2ea63a1220b1aa748f6a7f9b36b8e95 100644 --- a/src/mol-gl/shader/point.vert +++ b/src/mol-gl/shader/point.vert @@ -4,23 +4,27 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -precision mediump float; +precision highp float; uniform mat4 projection, model, view; -attribute vec3 position; //, color; -attribute vec4 transformColumn0, transformColumn1, transformColumn2, transformColumn3; -// attribute int instanceId; +uniform int objectId; +uniform int instanceCount; +uniform int elementCount; -// instanced -// attribute mat4 transform; -// uniform mat4 transform; +#pragma glslify: import('./chunks/color-vert-params.glsl') -// varying vec3 vColor; +attribute vec3 position; +attribute vec4 transformColumn0, transformColumn1, transformColumn2, transformColumn3; +attribute float instanceId; +attribute float elementId; void main(){ + #pragma glslify: import('./chunks/color-assign-varying.glsl') + mat4 transform = mat4(transformColumn0, transformColumn1, transformColumn2, transformColumn3); - // vColor = color; + mat4 modelView = view * model * transform; + gl_PointSize = 1.0; - gl_Position = projection * view * model * transform * vec4(position, 1.0); + gl_Position = projection * modelView * vec4(position, 1.0); } \ No newline at end of file diff --git a/src/mol-gl/shader/util/attenuation.glsl b/src/mol-gl/shader/utils/attenuation.glsl similarity index 100% rename from src/mol-gl/shader/util/attenuation.glsl rename to src/mol-gl/shader/utils/attenuation.glsl diff --git a/src/mol-gl/shader/util/inverse.glsl b/src/mol-gl/shader/utils/inverse.glsl similarity index 100% rename from src/mol-gl/shader/util/inverse.glsl rename to src/mol-gl/shader/utils/inverse.glsl diff --git a/src/mol-gl/shader/util/oren-nayar-diffuse.glsl b/src/mol-gl/shader/utils/oren-nayar-diffuse.glsl similarity index 100% rename from src/mol-gl/shader/util/oren-nayar-diffuse.glsl rename to src/mol-gl/shader/utils/oren-nayar-diffuse.glsl diff --git a/src/mol-gl/shader/util/phong-specular.glsl b/src/mol-gl/shader/utils/phong-specular.glsl similarity index 100% rename from src/mol-gl/shader/util/phong-specular.glsl rename to src/mol-gl/shader/utils/phong-specular.glsl diff --git a/src/mol-gl/shader/util/read-vec3.glsl b/src/mol-gl/shader/utils/read-vec3.glsl similarity index 100% rename from src/mol-gl/shader/util/read-vec3.glsl rename to src/mol-gl/shader/utils/read-vec3.glsl diff --git a/src/mol-gl/shader/util/transpose.glsl b/src/mol-gl/shader/utils/transpose.glsl similarity index 100% rename from src/mol-gl/shader/util/transpose.glsl rename to src/mol-gl/shader/utils/transpose.glsl diff --git a/src/mol-view/viewer.ts b/src/mol-view/viewer.ts index 14bf79505567800c730b308c55f66a5af4bafe43..785cd8fd048ca0c2aa6754f86cfa48b3037d7661 100644 --- a/src/mol-view/viewer.ts +++ b/src/mol-view/viewer.ts @@ -6,7 +6,7 @@ import { Vec3 } from 'mol-math/linear-algebra' import InputObserver from 'mol-util/input/input-observer' -import Renderer from 'mol-gl/renderer' +import Renderer, { RendererStats } from 'mol-gl/renderer' import { RenderObject } from 'mol-gl/scene' import TrackballControls from './controls/trackball' @@ -25,6 +25,7 @@ interface Viewer { handleResize: () => void + stats: RendererStats dispose: () => void } @@ -48,7 +49,6 @@ namespace Viewer { let drawPending = false function draw () { - controls.update() camera.update() renderer.draw() @@ -84,6 +84,9 @@ namespace Viewer { handleResize, + get stats() { + return renderer.stats + } dispose: () => { input.dispose() controls.dispose()