Bladeren bron

added multiSample helper

- fixes multiSample pass wih more than one viewport
Alexander Rose 4 jaren geleden
bovenliggende
commit
bd223b4c39

+ 4 - 3
src/mol-canvas3d/canvas3d.ts

@@ -25,7 +25,7 @@ import { DebugHelperParams } from './helper/bounding-sphere-helper';
 import { SetUtils } from '../mol-util/set';
 import { Canvas3dInteractionHelper } from './helper/interaction-events';
 import { PostprocessingParams, PostprocessingPass } from './passes/postprocessing';
-import { MultiSampleParams, MultiSamplePass } from './passes/multi-sample';
+import { MultiSampleHelper, MultiSampleParams, MultiSamplePass } from './passes/multi-sample';
 import { PickData } from './passes/pick';
 import { PickHelper } from './passes/pick';
 import { ImagePass, ImageProps } from './passes/image';
@@ -224,6 +224,7 @@ namespace Canvas3D {
 
         const pickHelper = new PickHelper(webgl, renderer, scene, helper, passes.pick, { x, y, width, height });
         const interactionHelper = new Canvas3dInteractionHelper(identify, getLoci, input, camera);
+        const multiSampleHelper = new MultiSampleHelper(passes.multiSample);
 
         let drawPending = false;
         let cameraResetRequested = false;
@@ -276,7 +277,7 @@ namespace Canvas3D {
             let didRender = false;
             controls.update(currentTime);
             const cameraChanged = camera.update();
-            const multiSampleChanged = passes.multiSample.update(force || cameraChanged, p.multiSample);
+            const multiSampleChanged = multiSampleHelper.update(force || cameraChanged, p.multiSample);
 
             if (force || cameraChanged || multiSampleChanged) {
                 let cam: Camera | StereoCamera = camera;
@@ -286,7 +287,7 @@ namespace Canvas3D {
                 }
 
                 if (MultiSamplePass.isEnabled(p.multiSample)) {
-                    passes.multiSample.render(renderer, cam, scene, helper, true, p.transparentBackground, p);
+                    multiSampleHelper.render(renderer, cam, scene, helper, true, p.transparentBackground, p);
                 } else {
                     const toDrawingBuffer = !PostprocessingPass.isEnabled(p.postprocessing) && scene.volumes.renderables.length === 0;
                     passes.draw.render(renderer, cam, scene, helper, toDrawingBuffer, p.transparentBackground);

+ 1 - 1
src/mol-canvas3d/controls/trackball.ts

@@ -68,7 +68,7 @@ namespace TrackballControls {
     export function create(input: InputObserver, camera: Camera, props: Partial<TrackballControlsProps> = {}): TrackballControls {
         const p = { ...PD.getDefaultValues(TrackballControlsParams), ...props };
 
-        const viewport = Viewport();
+        const viewport = Viewport.clone(camera.viewport);
 
         let disposed = false;
 

+ 14 - 13
src/mol-canvas3d/passes/image.ts

@@ -11,7 +11,7 @@ import Scene from '../../mol-gl/scene';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { DrawPass } from './draw';
 import { PostprocessingPass, PostprocessingParams } from './postprocessing';
-import { MultiSamplePass, MultiSampleParams } from './multi-sample';
+import { MultiSamplePass, MultiSampleParams, MultiSampleHelper } from './multi-sample';
 import { Camera } from '../camera';
 import { Viewport } from '../camera/util';
 import { PixelData } from '../../mol-util/image';
@@ -37,10 +37,10 @@ export class ImagePass {
     private _colorTarget: RenderTarget
     get colorTarget() { return this._colorTarget; }
 
-    readonly drawPass: DrawPass
-
-    private readonly postprocessing: PostprocessingPass
-    private readonly multiSample: MultiSamplePass
+    private readonly drawPass: DrawPass
+    private readonly postprocessingPass: PostprocessingPass
+    private readonly multiSamplePass: MultiSamplePass
+    private readonly multiSampleHelper: MultiSampleHelper
     private readonly helper: Helper
 
     get width() { return this._width; }
@@ -50,8 +50,9 @@ export class ImagePass {
         this.props = { ...PD.getDefaultValues(ImageParams), ...props };
 
         this.drawPass = new DrawPass(webgl, 128, 128);
-        this.postprocessing = new PostprocessingPass(webgl, this.drawPass);
-        this.multiSample = new MultiSamplePass(webgl, this.drawPass, this.postprocessing);
+        this.postprocessingPass = new PostprocessingPass(webgl, this.drawPass);
+        this.multiSamplePass = new MultiSamplePass(webgl, this.drawPass, this.postprocessingPass);
+        this.multiSampleHelper = new MultiSampleHelper(this.multiSamplePass);
 
         this.helper = {
             camera: new CameraHelper(webgl, this.props.cameraHelper),
@@ -69,8 +70,8 @@ export class ImagePass {
         this._height = height;
 
         this.drawPass.setSize(width, height);
-        this.postprocessing.syncSize();
-        this.multiSample.syncSize();
+        this.postprocessingPass.syncSize();
+        this.multiSamplePass.syncSize();
     }
 
     setProps(props: Partial<ImageProps> = {}) {
@@ -86,13 +87,13 @@ export class ImagePass {
         this.renderer.setViewport(0, 0, this._width, this._height);
 
         if (MultiSamplePass.isEnabled(this.props.multiSample)) {
-            this.multiSample.render(this.renderer, this._camera, this.scene, this.helper, false, this.props.transparentBackground, this.props);
-            this._colorTarget = this.multiSample.colorTarget;
+            this.multiSampleHelper.render(this.renderer, this._camera, this.scene, this.helper, false, this.props.transparentBackground, this.props);
+            this._colorTarget = this.multiSamplePass.colorTarget;
         } else {
             this.drawPass.render(this.renderer, this._camera, this.scene, this.helper, false, this.props.transparentBackground);
             if (PostprocessingPass.isEnabled(this.props.postprocessing)) {
-                this.postprocessing.render(this._camera, false, this.props.postprocessing);
-                this._colorTarget = this.postprocessing.target;
+                this.postprocessingPass.render(this._camera, false, this.props.postprocessing);
+                this._colorTarget = this.postprocessingPass.target;
             } else {
                 this._colorTarget = this.drawPass.colorTarget;
             }

+ 32 - 24
src/mol-canvas3d/passes/multi-sample.ts

@@ -68,8 +68,6 @@ export class MultiSamplePass {
     private holdTarget: RenderTarget
     private compose: ComposeRenderable
 
-    private sampleIndex = -2
-
     constructor(private webgl: WebGLContext, private drawPass: DrawPass, private postprocessing: PostprocessingPass) {
         const { extensions } = webgl;
         const width = drawPass.colorTarget.getWidth();
@@ -80,11 +78,6 @@ export class MultiSamplePass {
         this.compose = getComposeRenderable(webgl, drawPass.colorTarget.texture);
     }
 
-    update(changed: boolean, props: MultiSampleProps) {
-        if (changed) this.sampleIndex = -1;
-        return props.mode === 'temporal' ? this.sampleIndex !== -2 : false;
-    }
-
     syncSize() {
         const width = this.drawPass.colorTarget.getWidth();
         const height = this.drawPass.colorTarget.getHeight();
@@ -98,11 +91,12 @@ export class MultiSamplePass {
         }
     }
 
-    render(renderer: Renderer, camera: Camera | StereoCamera, scene: Scene, helper: Helper, toDrawingBuffer: boolean, transparentBackground: boolean, props: Props) {
+    render(sampleIndex: number, renderer: Renderer, camera: Camera | StereoCamera, scene: Scene, helper: Helper, toDrawingBuffer: boolean, transparentBackground: boolean, props: Props) {
         if (props.multiSample.mode === 'temporal') {
-            this.renderTemporalMultiSample(renderer, camera, scene, helper, toDrawingBuffer, transparentBackground, props);
+            return this.renderTemporalMultiSample(sampleIndex, renderer, camera, scene, helper, toDrawingBuffer, transparentBackground, props);
         } else {
             this.renderMultiSample(renderer, camera, scene, helper, toDrawingBuffer, transparentBackground, props);
+            return sampleIndex;
         }
     }
 
@@ -181,7 +175,7 @@ export class MultiSamplePass {
         camera.update();
     }
 
-    private renderTemporalMultiSample(renderer: Renderer, camera: Camera | StereoCamera, scene: Scene, helper: Helper, toDrawingBuffer: boolean, transparentBackground: boolean, props: Props) {
+    private renderTemporalMultiSample(sampleIndex: number, renderer: Renderer, camera: Camera | StereoCamera, scene: Scene, helper: Helper, toDrawingBuffer: boolean, transparentBackground: boolean, props: Props) {
         const { compose, composeTarget, holdTarget, postprocessing, drawPass, webgl } = this;
         const { gl, state } = webgl;
 
@@ -192,17 +186,13 @@ export class MultiSamplePass {
         // each sample with camera jitter and accumulates the results.
         const offsetList = JitterVectors[ Math.max(0, Math.min(props.multiSample.sampleLevel, 5)) ];
 
-        if (this.sampleIndex === -2) return;
-        if (this.sampleIndex >= offsetList.length) {
-            this.sampleIndex = -2;
-            return;
-        }
+        if (sampleIndex === -2 || sampleIndex >= offsetList.length) return -2;
 
         const { x, y, width, height } = camera.viewport;
         const sampleWeight = 1.0 / offsetList.length;
         const postprocessingEnabled = PostprocessingPass.isEnabled(props.postprocessing);
 
-        if (this.sampleIndex === -1) {
+        if (sampleIndex === -1) {
             drawPass.render(renderer, camera, scene, helper, false, transparentBackground);
             if (postprocessingEnabled) postprocessing.render(camera, false, props.postprocessing);
             ValueCell.update(compose.values.uWeight, 1.0);
@@ -216,7 +206,7 @@ export class MultiSamplePass {
             gl.viewport(x, y, width, height);
             gl.scissor(x, y, width, height);
             compose.render();
-            this.sampleIndex += 1;
+            sampleIndex += 1;
         } else {
             camera.viewOffset.enabled = true;
             ValueCell.update(compose.values.tColor, postprocessingEnabled ? postprocessing.target.texture : drawPass.colorTarget.texture);
@@ -227,7 +217,7 @@ export class MultiSamplePass {
             // from the last and accumulate the results.
             const numSamplesPerFrame = Math.pow(2, Math.max(0, props.multiSample.sampleLevel - 2));
             for (let i = 0; i < numSamplesPerFrame; ++i) {
-                const offset = offsetList[this.sampleIndex];
+                const offset = offsetList[sampleIndex];
                 Camera.setViewOffset(camera.viewOffset, width, height, offset[0], offset[1], width, height);
                 camera.update();
 
@@ -244,14 +234,14 @@ export class MultiSamplePass {
                 state.depthMask(false);
                 gl.viewport(x, y, width, height);
                 gl.scissor(x, y, width, height);
-                if (this.sampleIndex === 0) {
+                if (sampleIndex === 0) {
                     state.clearColor(0, 0, 0, 0);
                     gl.clear(gl.COLOR_BUFFER_BIT);
                 }
                 compose.render();
 
-                this.sampleIndex += 1;
-                if (this.sampleIndex >= offsetList.length ) break;
+                sampleIndex += 1;
+                if (sampleIndex >= offsetList.length ) break;
             }
         }
 
@@ -264,7 +254,7 @@ export class MultiSamplePass {
         gl.viewport(x, y, width, height);
         gl.scissor(x, y, width, height);
 
-        const accumulationWeight = this.sampleIndex * sampleWeight;
+        const accumulationWeight = sampleIndex * sampleWeight;
         if (accumulationWeight > 0) {
             ValueCell.update(compose.values.uWeight, 1.0);
             ValueCell.update(compose.values.tColor, composeTarget.texture);
@@ -283,7 +273,8 @@ export class MultiSamplePass {
 
         camera.viewOffset.enabled = false;
         camera.update();
-        if (this.sampleIndex >= offsetList.length) this.sampleIndex = -2;
+
+        return sampleIndex >= offsetList.length ? -2 : sampleIndex;
     }
 }
 
@@ -325,4 +316,21 @@ JitterVectors.forEach(offsetList => {
         offset[0] *= 0.0625;
         offset[1] *= 0.0625;
     });
-});
+});
+
+export class MultiSampleHelper {
+    private sampleIndex = -2
+
+    update(changed: boolean, props: MultiSampleProps) {
+        if (changed) this.sampleIndex = -1;
+        return props.mode === 'temporal' ? this.sampleIndex !== -2 : false;
+    }
+
+    render(renderer: Renderer, camera: Camera | StereoCamera, scene: Scene, helper: Helper, toDrawingBuffer: boolean, transparentBackground: boolean, props: Props) {
+        this.sampleIndex = this.multiSamplePass.render(this.sampleIndex, renderer, camera, scene, helper, toDrawingBuffer, transparentBackground, props);
+    }
+
+    constructor(private multiSamplePass: MultiSamplePass) {
+
+    }
+}

+ 7 - 3
src/mol-plugin/util/viewport-screenshot.ts

@@ -90,11 +90,15 @@ class ViewportScreenshotHelper {
     get imagePass() {
         if (this._imagePass) return this._imagePass;
 
-        this._imagePass = this.plugin.canvas3d!.getImagePass({
+        const c = this.plugin.canvas3d!;
+        this._imagePass = c.getImagePass({
             transparentBackground: this.transparent,
             cameraHelper: { axes: this.axes },
-            multiSample: { mode: 'on', sampleLevel: 2 },
-            postprocessing: this.plugin.canvas3d!.props.postprocessing
+            multiSample: {
+                mode: 'on',
+                sampleLevel: c.webgl.extensions.colorBufferFloat ? 4 : 2
+            },
+            postprocessing: c.props.postprocessing
         });
         return this._imagePass;
     }