From 51ced4f7626cdd4d7f6d813c7f7e2f7f47ea7a70 Mon Sep 17 00:00:00 2001 From: Alexander Rose <alex.rose@rcsb.org> Date: Fri, 17 May 2019 16:35:07 -0700 Subject: [PATCH] factored out draw-pass --- src/mol-canvas3d/canvas3d.ts | 57 +++--------------- src/mol-canvas3d/helper/draw.ts | 72 +++++++++++++++++++++++ src/mol-canvas3d/helper/multi-sample.ts | 28 ++++----- src/mol-canvas3d/helper/postprocessing.ts | 6 +- 4 files changed, 98 insertions(+), 65 deletions(-) create mode 100644 src/mol-canvas3d/helper/draw.ts diff --git a/src/mol-canvas3d/canvas3d.ts b/src/mol-canvas3d/canvas3d.ts index 4b8be2239..3a1e34838 100644 --- a/src/mol-canvas3d/canvas3d.ts +++ b/src/mol-canvas3d/canvas3d.ts @@ -26,12 +26,12 @@ import { BoundingSphereHelper, DebugHelperParams } from './helper/bounding-spher import { decodeFloatRGB } from 'mol-util/float-packing'; import { SetUtils } from 'mol-util/set'; import { Canvas3dInteractionHelper } from './helper/interaction-events'; -import { createTexture } from 'mol-gl/webgl/texture'; import { PostprocessingParams, PostprocessingPass } from './helper/postprocessing'; import { MultiSampleParams, MultiSamplePass } from './helper/multi-sample'; import { GLRenderingContext } from 'mol-gl/webgl/compat'; import { PixelData } from 'mol-util/image'; import { readTexture } from 'mol-gl/compute/util'; +import { DrawPass } from './helper/draw'; export const Canvas3DParams = { // TODO: FPS cap? @@ -129,17 +129,12 @@ namespace Canvas3D { const scene = Scene.create(webgl) const controls = TrackballControls.create(input, camera, p.trackball) const renderer = Renderer.create(webgl, camera, p.renderer) + const debugHelper = new BoundingSphereHelper(webgl, scene, p.debug); + const interactionHelper = new Canvas3dInteractionHelper(identify, getLoci, input); - const colorTarget = createRenderTarget(webgl, width, height) - const depthTarget = webgl.extensions.depthTexture ? null : createRenderTarget(webgl, width, height) - const depthTexture = depthTarget ? depthTarget.texture : createTexture(webgl, 'image-depth', 'depth', 'ushort', 'nearest') - if (!depthTarget) { - depthTexture.define(width, height) - depthTexture.attachFramebuffer(colorTarget.framebuffer, 'depth') - } - - const postprocessing = new PostprocessingPass(webgl, colorTarget.texture, depthTexture, !!depthTarget, p.postprocessing) - const multiSample = new MultiSamplePass(webgl, camera, colorTarget, postprocessing, renderDraw, p.multiSample) + const drawPass = new DrawPass(webgl, renderer, scene, debugHelper) + const postprocessing = new PostprocessingPass(webgl, drawPass, p.postprocessing) + const multiSample = new MultiSamplePass(webgl, camera, drawPass, postprocessing, p.multiSample) const pickBaseScale = 0.5 let pickScale = pickBaseScale / webgl.pixelRatio @@ -154,9 +149,6 @@ namespace Canvas3D { let isUpdating = false let drawPending = false - const debugHelper = new BoundingSphereHelper(webgl, scene, p.debug); - const interactionHelper = new Canvas3dInteractionHelper(identify, getLoci, input); - function getLoci(pickingId: PickingId) { let loci: Loci = EmptyLoci let repr: Representation.Any = Representation.Empty @@ -219,24 +211,6 @@ namespace Canvas3D { } } - function renderDraw() { - renderer.setViewport(0, 0, width, height) - renderer.render(scene, 'color', true) - if (debugHelper.isEnabled) { - debugHelper.syncVisibility() - renderer.render(debugHelper.scene, 'color', false) - } - - if (postprocessing.enabled && depthTarget) { - depthTarget.bind() - renderer.render(scene, 'depth', true) - if (debugHelper.isEnabled) { - debugHelper.syncVisibility() - renderer.render(debugHelper.scene, 'depth', false) - } - } - } - function render(variant: 'pick' | 'draw', force: boolean) { if (isIdentifying || isUpdating) return false @@ -263,9 +237,7 @@ namespace Canvas3D { if (multiSample.enabled) { multiSample.render() } else { - if (postprocessing.enabled) colorTarget.bind() - else webgl.unbindFramebuffer() - renderDraw() + drawPass.render(!postprocessing.enabled) if (postprocessing.enabled) postprocessing.render(true) } pickDirty = true @@ -430,12 +402,7 @@ namespace Canvas3D { case 'pickObject': return objectPickTarget.getPixelData() case 'pickInstance': return instancePickTarget.getPixelData() case 'pickGroup': return groupPickTarget.getPixelData() - case 'depth': - if (depthTarget) { - return depthTarget.getPixelData() - } else { - return readTexture(webgl, depthTexture) as PixelData - } + case 'depth': return readTexture(webgl, drawPass.depthTexture) as PixelData } }, didDraw, @@ -497,16 +464,10 @@ namespace Canvas3D { Viewport.set(camera.viewport, 0, 0, width, height) Viewport.set(controls.viewport, 0, 0, width, height) - colorTarget.setSize(width, height) + drawPass.setSize(width, height) postprocessing.setSize(width, height) multiSample.setSize(width, height) - if (depthTarget) { - depthTarget.setSize(width, height) - } else { - depthTexture.define(width, height) - } - pickScale = pickBaseScale / webgl.pixelRatio pickWidth = Math.round(width * pickScale) pickHeight = Math.round(height * pickScale) diff --git a/src/mol-canvas3d/helper/draw.ts b/src/mol-canvas3d/helper/draw.ts new file mode 100644 index 000000000..7b39e0a05 --- /dev/null +++ b/src/mol-canvas3d/helper/draw.ts @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import { WebGLContext } from 'mol-gl/webgl/context'; +import { createRenderTarget, RenderTarget } from 'mol-gl/webgl/render-target'; +import Renderer from 'mol-gl/renderer'; +import Scene from 'mol-gl/scene'; +import { BoundingSphereHelper } from './bounding-sphere-helper'; +import { createTexture, Texture } from 'mol-gl/webgl/texture'; + + +export class DrawPass { + colorTarget: RenderTarget + depthTexture: Texture + packedDepth: boolean + + private depthTarget: RenderTarget | null + + constructor(private webgl: WebGLContext, private renderer: Renderer, private scene: Scene, private debugHelper: BoundingSphereHelper) { + const { gl, extensions } = webgl + const width = gl.drawingBufferWidth + const height = gl.drawingBufferHeight + this.colorTarget = createRenderTarget(webgl, gl.drawingBufferWidth, gl.drawingBufferHeight) + this.packedDepth = !extensions.depthTexture + this.depthTarget = this.packedDepth ? createRenderTarget(webgl, width, height) : null + this.depthTexture = this.depthTarget ? this.depthTarget.texture : createTexture(webgl, 'image-depth', 'depth', 'ushort', 'nearest') + if (!this.packedDepth) { + this.depthTexture.define(width, height) + this.depthTexture.attachFramebuffer(this.colorTarget.framebuffer, 'depth') + } + } + + setSize(width: number, height: number) { + this.colorTarget.setSize(width, height) + if (this.depthTarget) { + this.depthTarget.setSize(width, height) + } else { + this.depthTexture.define(width, height) + } + } + + render(toDrawingBuffer: boolean) { + const { webgl, renderer, scene, debugHelper, colorTarget, depthTarget } = this + const { gl } = webgl + if (toDrawingBuffer) { + webgl.unbindFramebuffer() + gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight) + } else { + colorTarget.bind() + } + renderer.setViewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight) + renderer.render(scene, 'color', true) + if (debugHelper.isEnabled) { + debugHelper.syncVisibility() + renderer.render(debugHelper.scene, 'color', false) + } + + // do a depth pass if not rendering to drawing buffer and + // extensions.depthTexture is unsupported (i.e. depthTarget is set) + if (!toDrawingBuffer && depthTarget) { + depthTarget.bind() + renderer.render(scene, 'depth', true) + if (debugHelper.isEnabled) { + debugHelper.syncVisibility() + renderer.render(debugHelper.scene, 'depth', false) + } + } + } +} \ No newline at end of file diff --git a/src/mol-canvas3d/helper/multi-sample.ts b/src/mol-canvas3d/helper/multi-sample.ts index 858533309..06ccc2c31 100644 --- a/src/mol-canvas3d/helper/multi-sample.ts +++ b/src/mol-canvas3d/helper/multi-sample.ts @@ -17,6 +17,7 @@ import { ParamDefinition as PD } from 'mol-util/param-definition'; import { RenderTarget, createRenderTarget } from 'mol-gl/webgl/render-target'; import { Camera } from 'mol-canvas3d/camera'; import { PostprocessingPass } from './postprocessing'; +import { DrawPass } from './draw'; const ComposeSchema = { ...QuadSchema, @@ -62,11 +63,11 @@ export class MultiSamplePass { private currentTime = 0 private lastRenderTime = 0 - constructor(private webgl: WebGLContext, private camera: Camera, private colorTarget: RenderTarget, private postprocessing: PostprocessingPass, private renderDraw: () => void, props: Partial<MultiSampleProps>) { + constructor(private webgl: WebGLContext, private camera: Camera, private drawPass: DrawPass, private postprocessing: PostprocessingPass, props: Partial<MultiSampleProps>) { const { gl } = webgl this.composeTarget = createRenderTarget(webgl, gl.drawingBufferWidth, gl.drawingBufferHeight) this.holdTarget = createRenderTarget(webgl, gl.drawingBufferWidth, gl.drawingBufferHeight) - this.compose = getComposeRenderable(webgl, colorTarget.texture) + this.compose = getComposeRenderable(webgl, drawPass.colorTarget.texture) this.props = { ...PD.getDefaultValues(MultiSampleParams), ...props } } @@ -110,7 +111,7 @@ export class MultiSamplePass { } private renderMultiSample() { - const { camera, compose, colorTarget, composeTarget, postprocessing, renderDraw, webgl } = this + const { camera, compose, composeTarget, drawPass, postprocessing, webgl } = this const { gl, state } = webgl // based on the Multisample Anti-Aliasing Render Pass @@ -124,10 +125,10 @@ export class MultiSamplePass { const roundingRange = 1 / 32 camera.viewOffset.enabled = true - ValueCell.update(compose.values.tColor, postprocessing.enabled ? postprocessing.target.texture : colorTarget.texture) + ValueCell.update(compose.values.tColor, postprocessing.enabled ? postprocessing.target.texture : drawPass.colorTarget.texture) compose.update() - const { width, height } = colorTarget + const { width, height } = drawPass.colorTarget // render the scene multiple times, each slightly jitter offset // from the last and accumulate the results. @@ -144,8 +145,7 @@ export class MultiSamplePass { ValueCell.update(compose.values.uWeight, sampleWeight) // render scene and optionally postprocess - colorTarget.bind() - renderDraw() + drawPass.render(false) if (postprocessing.enabled) postprocessing.render(false) // compose rendered scene with compose target @@ -178,7 +178,7 @@ export class MultiSamplePass { } private renderTemporalMultiSample() { - const { camera, compose, colorTarget, composeTarget, holdTarget, postprocessing, renderDraw, webgl } = this + const { camera, compose, composeTarget, holdTarget, postprocessing, drawPass, webgl } = this const { gl, state } = webgl // based on the Multisample Anti-Aliasing Render Pass @@ -197,11 +197,10 @@ export class MultiSamplePass { const i = this.sampleIndex if (i === 0) { - colorTarget.bind() - renderDraw() + drawPass.render(false) if (postprocessing.enabled) postprocessing.render(false) ValueCell.update(compose.values.uWeight, 1.0) - ValueCell.update(compose.values.tColor, postprocessing.enabled ? postprocessing.target.texture : colorTarget.texture) + ValueCell.update(compose.values.tColor, postprocessing.enabled ? postprocessing.target.texture : drawPass.colorTarget.texture) compose.update() holdTarget.bind() @@ -212,11 +211,11 @@ export class MultiSamplePass { const sampleWeight = 1.0 / offsetList.length camera.viewOffset.enabled = true - ValueCell.update(compose.values.tColor, postprocessing.enabled ? postprocessing.target.texture : colorTarget.texture) + ValueCell.update(compose.values.tColor, postprocessing.enabled ? postprocessing.target.texture : drawPass.colorTarget.texture) ValueCell.update(compose.values.uWeight, sampleWeight) compose.update() - const { width, height } = colorTarget + const { width, height } = drawPass.colorTarget // render the scene multiple times, each slightly jitter offset // from the last and accumulate the results. @@ -227,8 +226,7 @@ export class MultiSamplePass { camera.updateMatrices() // render scene and optionally postprocess - colorTarget.bind() - renderDraw() + drawPass.render(false) if (postprocessing.enabled) postprocessing.render(false) // compose rendered scene with compose target diff --git a/src/mol-canvas3d/helper/postprocessing.ts b/src/mol-canvas3d/helper/postprocessing.ts index eb54c3a42..32b8cb8b7 100644 --- a/src/mol-canvas3d/helper/postprocessing.ts +++ b/src/mol-canvas3d/helper/postprocessing.ts @@ -15,6 +15,7 @@ import { createComputeRenderable, ComputeRenderable } from 'mol-gl/renderable'; import { Vec2 } from 'mol-math/linear-algebra'; import { ParamDefinition as PD } from 'mol-util/param-definition'; import { createRenderTarget, RenderTarget } from 'mol-gl/webgl/render-target'; +import { DrawPass } from './draw'; const PostprocessingSchema = { ...QuadSchema, @@ -83,11 +84,12 @@ export class PostprocessingPass { props: PostprocessingProps renderable: PostprocessingRenderable - constructor(private webgl: WebGLContext, colorTexture: Texture, depthTexture: Texture, packedDepth: boolean, props: Partial<PostprocessingProps>) { + constructor(private webgl: WebGLContext, drawPass: DrawPass, props: Partial<PostprocessingProps>) { const { gl } = webgl this.target = createRenderTarget(webgl, gl.drawingBufferWidth, gl.drawingBufferHeight) this.props = { ...PD.getDefaultValues(PostprocessingParams), ...props } - this.renderable = getPostprocessingRenderable(webgl, colorTexture, depthTexture, packedDepth, this.props) + const { colorTarget, depthTexture, packedDepth } = drawPass + this.renderable = getPostprocessingRenderable(webgl, colorTarget.texture, depthTexture, packedDepth, this.props) } get enabled() { -- GitLab