diff --git a/src/mol-canvas3d/canvas3d.ts b/src/mol-canvas3d/canvas3d.ts index e4491ed0f88c6e563d3637a4bcdeb38108b25c2a..09f1abea6af0831032ffebaacd9ddc3d2797fb3b 100644 --- a/src/mol-canvas3d/canvas3d.ts +++ b/src/mol-canvas3d/canvas3d.ts @@ -19,7 +19,7 @@ import { createContext, getGLContext, WebGLContext } from 'mol-gl/webgl/context' import { Representation } from 'mol-repr/representation'; import { createRenderTarget } from 'mol-gl/webgl/render-target'; import Scene from 'mol-gl/scene'; -import { RenderVariant } from 'mol-gl/webgl/render-item'; +import { GraphicsRenderVariant } from 'mol-gl/webgl/render-item'; import { PickingId } from 'mol-geo/geometry/picking'; import { MarkerAction } from 'mol-geo/geometry/marker-data'; import { Loci, EmptyLoci, isEmptyLoci } from 'mol-model/loci'; @@ -70,7 +70,7 @@ interface Canvas3D { resetCamera: () => void readonly camera: Camera downloadScreenshot: () => void - getImageData: (variant: RenderVariant) => ImageData + getImageData: (variant: GraphicsRenderVariant) => ImageData setProps: (props: Partial<Canvas3DProps>) => void /** Returns a copy of the current Canvas3D instance props */ @@ -388,7 +388,7 @@ namespace Canvas3D { downloadScreenshot: () => { // TODO }, - getImageData: (variant: RenderVariant) => { + getImageData: (variant: GraphicsRenderVariant) => { switch (variant) { case 'draw': return renderer.getImageData() case 'pickObject': return objectPickTarget.getImageData() diff --git a/src/mol-gl/renderable.ts b/src/mol-gl/renderable.ts index bd436980ba0b8869aba530be51f272ad49c66bce..62817b1e0e2393643a79441affb2aef35dace72f 100644 --- a/src/mol-gl/renderable.ts +++ b/src/mol-gl/renderable.ts @@ -6,7 +6,7 @@ import { Program } from './webgl/program'; import { RenderableValues, Values, RenderableSchema } from './renderable/schema'; -import { RenderVariant, RenderItem } from './webgl/render-item'; +import { GraphicsRenderItem, ComputeRenderItem, GraphicsRenderVariant } from './webgl/render-item'; import { ValueCell } from 'mol-util'; import { idFactory } from 'mol-util/id-factory'; import { clamp } from 'mol-math/interpolate'; @@ -26,20 +26,20 @@ export interface Renderable<T extends RenderableValues> { readonly values: T readonly state: RenderableState - render: (variant: RenderVariant) => void - getProgram: (variant: RenderVariant) => Program + render: (variant: GraphicsRenderVariant) => void + getProgram: (variant: GraphicsRenderVariant) => Program update: () => void dispose: () => void } -export function createRenderable<T extends Values<RenderableSchema>>(renderItem: RenderItem, values: T, state: RenderableState): Renderable<T> { +export function createRenderable<T extends Values<RenderableSchema>>(renderItem: GraphicsRenderItem, values: T, state: RenderableState): Renderable<T> { return { id: getNextRenderableId(), materialId: renderItem.materialId, values, state, - render: (variant: RenderVariant) => { + render: (variant: GraphicsRenderVariant) => { if (values.uAlpha && values.alpha) { ValueCell.updateIfChanged(values.uAlpha, clamp(values.alpha.ref.value * state.alphaFactor, 0, 1)) } @@ -48,7 +48,7 @@ export function createRenderable<T extends Values<RenderableSchema>>(renderItem: } renderItem.render(variant) }, - getProgram: (variant: RenderVariant) => renderItem.getProgram(variant), + getProgram: (variant: GraphicsRenderVariant) => renderItem.getProgram(variant), update: () => renderItem.update(), dispose: () => renderItem.destroy() } @@ -66,13 +66,13 @@ export interface ComputeRenderable<T extends RenderableValues> { dispose: () => void } -export function createComputeRenderable<T extends Values<RenderableSchema>>(renderItem: RenderItem, values: T): ComputeRenderable<T> { +export function createComputeRenderable<T extends Values<RenderableSchema>>(renderItem: ComputeRenderItem, values: T): ComputeRenderable<T> { return { id: getNextRenderableId(), values, - render: () => renderItem.render('draw'), - use: () => renderItem.getProgram('draw').use(), + render: () => renderItem.render('compute'), + use: () => renderItem.getProgram('compute').use(), update: () => renderItem.update(), dispose: () => renderItem.destroy() } diff --git a/src/mol-gl/renderable/direct-volume.ts b/src/mol-gl/renderable/direct-volume.ts index 53583cbdf97267ca43cb46ae31d065ebb3f25bbc..89b77527892f2972e8599218d1ab4ffbc9bb10b2 100644 --- a/src/mol-gl/renderable/direct-volume.ts +++ b/src/mol-gl/renderable/direct-volume.ts @@ -6,7 +6,7 @@ import { Renderable, RenderableState, createRenderable } from '../renderable' import { WebGLContext } from '../webgl/context'; -import { createRenderItem } from '../webgl/render-item'; +import { createGraphicsRenderItem } from '../webgl/render-item'; import { AttributeSpec, Values, UniformSpec, GlobalUniformSchema, InternalSchema, TextureSpec, ValueSpec, ElementsSpec, DefineSpec, InternalValues } from './schema'; import { DirectVolumeShaderCode } from '../shader-code'; import { ValueCell } from 'mol-util'; @@ -79,6 +79,6 @@ export function DirectVolumeRenderable(ctx: WebGLContext, id: number, values: Di uPickable: ValueCell.create(state.pickable ? 1 : 0), } const shaderCode = DirectVolumeShaderCode - const renderItem = createRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId) + const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId) return createRenderable(renderItem, values, state); } \ No newline at end of file diff --git a/src/mol-gl/renderable/lines.ts b/src/mol-gl/renderable/lines.ts index 74fcca839773656e9d5c67aa0baddfc3479eba08..e44a62f727944a953bf33ada6fcc43307fd2b3dc 100644 --- a/src/mol-gl/renderable/lines.ts +++ b/src/mol-gl/renderable/lines.ts @@ -6,7 +6,7 @@ import { Renderable, RenderableState, createRenderable } from '../renderable' import { WebGLContext } from '../webgl/context'; -import { createRenderItem } from '../webgl/render-item'; +import { createGraphicsRenderItem } from '../webgl/render-item'; import { GlobalUniformSchema, BaseSchema, AttributeSpec, DefineSpec, Values, InternalSchema, SizeSchema, ElementsSpec, InternalValues } from './schema'; import { ValueCell } from 'mol-util'; import { LinesShaderCode } from '../shader-code'; @@ -32,7 +32,7 @@ export function LinesRenderable(ctx: WebGLContext, id: number, values: LinesValu uPickable: ValueCell.create(state.pickable ? 1 : 0) } const shaderCode = LinesShaderCode - const renderItem = createRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId) + const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId) return createRenderable(renderItem, values, state); } \ No newline at end of file diff --git a/src/mol-gl/renderable/mesh.ts b/src/mol-gl/renderable/mesh.ts index a8ebba4b3942e0937efe47caf654bbee916c0c23..bcf65b9f0901227dc3407c7e64832fdb434ecc14 100644 --- a/src/mol-gl/renderable/mesh.ts +++ b/src/mol-gl/renderable/mesh.ts @@ -6,7 +6,7 @@ import { Renderable, RenderableState, createRenderable } from '../renderable' import { WebGLContext } from '../webgl/context'; -import { createRenderItem } from '../webgl/render-item'; +import { createGraphicsRenderItem } from '../webgl/render-item'; import { GlobalUniformSchema, BaseSchema, AttributeSpec, ElementsSpec, DefineSpec, Values, InternalSchema, InternalValues } from './schema'; import { MeshShaderCode } from '../shader-code'; import { ValueCell } from 'mol-util'; @@ -30,7 +30,7 @@ export function MeshRenderable(ctx: WebGLContext, id: number, values: MeshValues uPickable: ValueCell.create(state.pickable ? 1 : 0) } const shaderCode = MeshShaderCode - const renderItem = createRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId) + const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId) return createRenderable(renderItem, values, state) } \ No newline at end of file diff --git a/src/mol-gl/renderable/points.ts b/src/mol-gl/renderable/points.ts index ff3726edb43cae8d1769ee5318820d38db74f7b0..6b2cf5e1a3e69891055c76e22fd39d28baae3c00 100644 --- a/src/mol-gl/renderable/points.ts +++ b/src/mol-gl/renderable/points.ts @@ -6,7 +6,7 @@ import { Renderable, RenderableState, createRenderable } from '../renderable' import { WebGLContext } from '../webgl/context'; -import { createRenderItem } from '../webgl/render-item'; +import { createGraphicsRenderItem } from '../webgl/render-item'; import { GlobalUniformSchema, BaseSchema, AttributeSpec, UniformSpec, DefineSpec, Values, InternalSchema, SizeSchema, InternalValues } from './schema'; import { PointsShaderCode } from '../shader-code'; import { ValueCell } from 'mol-util'; @@ -29,6 +29,6 @@ export function PointsRenderable(ctx: WebGLContext, id: number, values: PointsVa uPickable: ValueCell.create(state.pickable ? 1 : 0) } const shaderCode = PointsShaderCode - const renderItem = createRenderItem(ctx, 'points', shaderCode, schema, { ...values, ...internalValues }, materialId) + const renderItem = createGraphicsRenderItem(ctx, 'points', shaderCode, schema, { ...values, ...internalValues }, materialId) return createRenderable(renderItem, values, state); } \ No newline at end of file diff --git a/src/mol-gl/renderable/spheres.ts b/src/mol-gl/renderable/spheres.ts index 3806cf18304240f7f7e8256b00f8fcd11572f4a5..1af5348ec7029a76e0dd93dc790eaeac20967cc0 100644 --- a/src/mol-gl/renderable/spheres.ts +++ b/src/mol-gl/renderable/spheres.ts @@ -6,7 +6,7 @@ import { Renderable, RenderableState, createRenderable } from '../renderable' import { WebGLContext } from '../webgl/context'; -import { createRenderItem } from '../webgl/render-item'; +import { createGraphicsRenderItem } from '../webgl/render-item'; import { GlobalUniformSchema, BaseSchema, AttributeSpec, Values, InternalSchema, SizeSchema, InternalValues, ElementsSpec, ValueSpec, DefineSpec } from './schema'; import { SpheresShaderCode } from '../shader-code'; import { ValueCell } from 'mol-util'; @@ -31,6 +31,6 @@ export function SpheresRenderable(ctx: WebGLContext, id: number, values: Spheres uPickable: ValueCell.create(state.pickable ? 1 : 0) } const shaderCode = SpheresShaderCode - const renderItem = createRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId) + const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId) return createRenderable(renderItem, values, state); } \ No newline at end of file diff --git a/src/mol-gl/renderable/text.ts b/src/mol-gl/renderable/text.ts index 3e9a2c4764de39404ec00a6d20b919c8934561e8..1bf43a8569bf25c8cb22efa3bff6730b7f99b61e 100644 --- a/src/mol-gl/renderable/text.ts +++ b/src/mol-gl/renderable/text.ts @@ -6,7 +6,7 @@ import { Renderable, RenderableState, createRenderable } from '../renderable' import { WebGLContext } from '../webgl/context'; -import { createRenderItem } from '../webgl/render-item'; +import { createGraphicsRenderItem } from '../webgl/render-item'; import { GlobalUniformSchema, BaseSchema, AttributeSpec, UniformSpec, Values, InternalSchema, SizeSchema, InternalValues, TextureSpec, ElementsSpec, ValueSpec } from './schema'; import { TextShaderCode } from '../shader-code'; import { ValueCell } from 'mol-util'; @@ -41,6 +41,6 @@ export function TextRenderable(ctx: WebGLContext, id: number, values: TextValues uPickable: ValueCell.create(state.pickable ? 1 : 0) } const shaderCode = TextShaderCode - const renderItem = createRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId) + const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId) return createRenderable(renderItem, values, state); } \ No newline at end of file diff --git a/src/mol-gl/renderer.ts b/src/mol-gl/renderer.ts index d56dcbe1bb409a0237b84a8da06452f683f3bba1..fbc6b146f553299559fcedb5a3f75723df6cb031 100644 --- a/src/mol-gl/renderer.ts +++ b/src/mol-gl/renderer.ts @@ -14,7 +14,7 @@ import { Renderable } from './renderable'; import { Color } from 'mol-util/color'; import { ValueCell } from 'mol-util'; import { RenderableValues, GlobalUniformValues, BaseValues } from './renderable/schema'; -import { RenderVariant } from './webgl/render-item'; +import { GraphicsRenderVariant } from './webgl/render-item'; export interface RendererStats { programCount: number @@ -36,7 +36,7 @@ interface Renderer { readonly props: RendererProps clear: () => void - render: (scene: Scene, variant: RenderVariant) => void + render: (scene: Scene, variant: GraphicsRenderVariant) => void setViewport: (x: number, y: number, width: number, height: number) => void setClearColor: (color: Color) => void setPickingAlphaThreshold: (value: number) => void @@ -108,7 +108,7 @@ namespace Renderer { const globalUniformList = Object.entries(globalUniforms) let globalUniformsNeedUpdate = true - const renderObject = (r: Renderable<RenderableValues & BaseValues>, variant: RenderVariant) => { + const renderObject = (r: Renderable<RenderableValues & BaseValues>, variant: GraphicsRenderVariant) => { const program = r.getProgram(variant) if (r.state.visible) { if (state.currentProgramId !== program.id) { @@ -152,7 +152,7 @@ namespace Renderer { } } - const render = (scene: Scene, variant: RenderVariant) => { + const render = (scene: Scene, variant: GraphicsRenderVariant) => { ValueCell.update(globalUniforms.uModel, scene.view) ValueCell.update(globalUniforms.uView, camera.view) ValueCell.update(globalUniforms.uInvView, Mat4.invert(invView, camera.view)) diff --git a/src/mol-gl/webgl/render-item.ts b/src/mol-gl/webgl/render-item.ts index 45c057d29f0b4038f1954e5e1d909fdd7ea4508f..763a6e67010172af382acd2df976a31facf06f1d 100644 --- a/src/mol-gl/webgl/render-item.ts +++ b/src/mol-gl/webgl/render-item.ts @@ -33,23 +33,34 @@ export function getDrawMode(ctx: WebGLContext, drawMode: DrawMode) { } } -export interface RenderItem { +export interface RenderItem<T extends string> { readonly id: number readonly materialId: number - getProgram: (variant: RenderVariant) => Program + getProgram: (variant: T) => Program - render: (variant: RenderVariant) => void + render: (variant: T) => void update: () => Readonly<ValueChanges> destroy: () => void } -const RenderVariantDefines = { +// + +const GraphicsRenderVariantDefines = { 'draw': {}, 'pickObject': { dColorType: ValueCell.create('objectPicking') }, 'pickInstance': { dColorType: ValueCell.create('instancePicking') }, 'pickGroup': { dColorType: ValueCell.create('groupPicking') } } -export type RenderVariant = keyof typeof RenderVariantDefines +export type GraphicsRenderVariant = keyof typeof GraphicsRenderVariantDefines + +const ComputeRenderVariantDefines = { + 'compute': {}, +} +export type ComputeRenderVariant = keyof typeof ComputeRenderVariantDefines + +type RenderVariantDefines = typeof GraphicsRenderVariantDefines | typeof ComputeRenderVariantDefines + +// type ProgramVariants = { [k: string]: ReferenceItem<Program> } type VertexArrayVariants = { [k: string]: WebGLVertexArrayObjectOES | null } @@ -75,14 +86,24 @@ function resetValueChanges(valueChanges: ValueChanges) { valueChanges.textures = false } -// TODO make `RenderVariantDefines` a parameter for `createRenderItem` +// + +export type GraphicsRenderItem = RenderItem<keyof typeof GraphicsRenderVariantDefines & string> +export function createGraphicsRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCode: ShaderCode, schema: RenderableSchema, values: RenderableValues, materialId: number) { + return createRenderItem(ctx, drawMode, shaderCode, schema, values, materialId, GraphicsRenderVariantDefines) +} + +export type ComputeRenderItem = RenderItem<keyof typeof ComputeRenderVariantDefines & string> +export function createComputeRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCode: ShaderCode, schema: RenderableSchema, values: RenderableValues) { + return createRenderItem(ctx, drawMode, shaderCode, schema, values, -1, ComputeRenderVariantDefines) +} /** * Creates a render item * * - assumes that `values.drawCount` and `values.instanceCount` exist */ -export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCode: ShaderCode, schema: RenderableSchema, values: RenderableValues, materialId: number): RenderItem { +export function createRenderItem<T extends RenderVariantDefines, S extends keyof T & string>(ctx: WebGLContext, drawMode: DrawMode, shaderCode: ShaderCode, schema: RenderableSchema, values: RenderableValues, materialId: number, renderVariantDefines: T): RenderItem<S> { const id = getNextRenderItemId() const { stats, state, programCache } = ctx const { instancedArrays, vertexArrayObject } = ctx.extensions @@ -98,8 +119,8 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo const glDrawMode = getDrawMode(ctx, drawMode) const programs: ProgramVariants = {} - Object.keys(RenderVariantDefines).forEach(k => { - const variantDefineValues: Values<RenderableSchema> = (RenderVariantDefines as any)[k] + Object.keys(renderVariantDefines).forEach(k => { + const variantDefineValues: Values<RenderableSchema> = (renderVariantDefines as any)[k] programs[k] = programCache.get({ defineValues: { ...defineValues, ...variantDefineValues }, shaderCode, @@ -117,7 +138,7 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo } const vertexArrays: VertexArrayVariants = {} - Object.keys(RenderVariantDefines).forEach(k => { + Object.keys(renderVariantDefines).forEach(k => { vertexArrays[k] = createVertexArray(ctx, programs[k].value, attributeBuffers, elementsBuffer) }) @@ -136,9 +157,9 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo return { id, materialId, - getProgram: (variant: RenderVariant) => programs[variant].value, + getProgram: (variant: S) => programs[variant].value, - render: (variant: RenderVariant) => { + render: (variant: S) => { if (drawCount === 0 || instanceCount === 0) return const program = programs[variant].value const vertexArray = vertexArrays[variant] @@ -180,8 +201,8 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo if (valueChanges.defines) { // console.log('some defines changed, need to rebuild programs') - Object.keys(RenderVariantDefines).forEach(k => { - const variantDefineValues: Values<RenderableSchema> = (RenderVariantDefines as any)[k] + Object.keys(renderVariantDefines).forEach(k => { + const variantDefineValues: Values<RenderableSchema> = (renderVariantDefines as any)[k] programs[k].free() programs[k] = programCache.get({ defineValues: { ...defineValues, ...variantDefineValues }, @@ -241,7 +262,7 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo // console.log('program/defines or buffers changed, update vaos') const { vertexArrayObject } = ctx.extensions if (vertexArrayObject) { - Object.keys(RenderVariantDefines).forEach(k => { + Object.keys(renderVariantDefines).forEach(k => { vertexArrayObject.bindVertexArray(vertexArrays[k]) if (elementsBuffer && (valueChanges.defines || valueChanges.elements)) { elementsBuffer.bind() @@ -274,7 +295,7 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo }, destroy: () => { if (!destroyed) { - Object.keys(RenderVariantDefines).forEach(k => { + Object.keys(renderVariantDefines).forEach(k => { programs[k].free() deleteVertexArray(ctx, vertexArrays[k]) })