Browse Source

factored out draw-pass

Alexander Rose 5 years ago
parent
commit
51ced4f762

+ 9 - 48
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)

+ 72 - 0
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)
+            }
+        }
+    }
+}

+ 13 - 15
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

+ 4 - 2
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() {