Bladeren bron

added graphics and compute render item variants

Alexander Rose 6 jaren geleden
bovenliggende
commit
f28313fd2d

+ 3 - 3
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()

+ 9 - 9
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()
     }

+ 2 - 2
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);
 }

+ 2 - 2
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);
 }

+ 2 - 2
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)
 }

+ 2 - 2
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);
 }

+ 2 - 2
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);
 }

+ 2 - 2
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);
 }

+ 4 - 4
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))

+ 37 - 16
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])
                 })