diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f8bdc0fa357e93c5f9c7283ded1fe9cd0ea1315..98f295751a98b78bc0802e26d02585d848156453 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Note that since we don't clearly distinguish between a public and private interf - Add ``UnitResonance`` property with info about delocalized triplets - Resolve marking in main renderer loop to improve overall performance - Use ``throttleTime`` instead of ``debounceTime`` in sequence viewer for better responsiveness +- Reuse occlusion for secondary passes during multi-sampling ## [v3.2.0] - 2022-02-17 diff --git a/src/mol-canvas3d/passes/multi-sample.ts b/src/mol-canvas3d/passes/multi-sample.ts index dba08fb53c10aa61c3d792bbb743ed2b7197747d..6f7ca4358d657622ad81bbd9186d28857622d6f4 100644 --- a/src/mol-canvas3d/passes/multi-sample.ts +++ b/src/mol-canvas3d/passes/multi-sample.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ @@ -157,6 +157,14 @@ export class MultiSamplePass { ValueCell.update(compose.values.uWeight, sampleWeight); // render scene + if (i === 0) { + drawPass.postprocessing.setOcclusionOffset(0, 0); + } else { + drawPass.postprocessing.setOcclusionOffset( + offset[0] / width, + offset[1] / height + ); + } drawPass.render(ctx, props, false); // compose rendered scene with compose target @@ -175,6 +183,8 @@ export class MultiSamplePass { compose.render(); } + drawPass.postprocessing.setOcclusionOffset(0, 0); + ValueCell.update(compose.values.uWeight, 1.0); ValueCell.update(compose.values.tColor, composeTarget.texture); compose.update(); @@ -236,6 +246,14 @@ export class MultiSamplePass { camera.update(); // render scene + if (sampleIndex === 0) { + drawPass.postprocessing.setOcclusionOffset(0, 0); + } else { + drawPass.postprocessing.setOcclusionOffset( + offset[0] / width, + offset[1] / height + ); + } drawPass.render(ctx, props, false); // compose rendered scene with compose target @@ -258,6 +276,8 @@ export class MultiSamplePass { } } + drawPass.postprocessing.setOcclusionOffset(0, 0); + this.bindOutputTarget(toDrawingBuffer); gl.viewport(x, y, width, height); gl.scissor(x, y, width, height); @@ -291,23 +311,23 @@ const JitterVectors = [ [0, 0] ], [ - [4, 4], [-4, -4] + [0, 0], [-4, -4] ], [ - [-2, -6], [6, -2], [-6, 2], [2, 6] + [0, 0], [6, -2], [-6, 2], [2, 6] ], [ - [1, -3], [-1, 3], [5, 1], [-3, -5], + [0, 0], [-1, 3], [5, 1], [-3, -5], [-5, 5], [-7, -1], [3, 7], [7, -7] ], [ - [1, 1], [-1, -3], [-3, 2], [4, -1], + [0, 0], [-1, -3], [-3, 2], [4, -1], [-5, -2], [2, 5], [5, 3], [3, -5], [-2, 6], [0, -7], [-4, -6], [-6, 4], [-8, 0], [7, -4], [6, 7], [-7, -8] ], [ - [-4, -7], [-7, -5], [-3, -5], [-5, -4], + [0, 0], [-7, -5], [-3, -5], [-5, -4], [-1, -4], [-2, -2], [-6, -1], [-4, 0], [-7, 1], [-1, 2], [-6, 3], [-3, 3], [-7, 6], [-3, 6], [-5, 7], [-1, 7], diff --git a/src/mol-canvas3d/passes/postprocessing.ts b/src/mol-canvas3d/passes/postprocessing.ts index e6904f4c79ad45e2e7688c53131e54d33c6445f2..dfc2ec876940042c45663041740db7754d5da514 100644 --- a/src/mol-canvas3d/passes/postprocessing.ts +++ b/src/mol-canvas3d/passes/postprocessing.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Áron Samuel Kovács <aron.kovacs@mail.muni.cz> @@ -199,6 +199,7 @@ const PostprocessingSchema = { uMaxPossibleViewZDiff: UniformSpec('f'), dOcclusionEnable: DefineSpec('boolean'), + uOcclusionOffset: UniformSpec('v2'), dOutlineEnable: DefineSpec('boolean'), dOutlineScale: DefineSpec('number'), @@ -227,6 +228,7 @@ function getPostprocessingRenderable(ctx: WebGLContext, colorTexture: Texture, d uMaxPossibleViewZDiff: ValueCell.create(0.5), dOcclusionEnable: ValueCell.create(true), + uOcclusionOffset: ValueCell.create(Vec2.create(0, 0)), dOutlineEnable: ValueCell.create(false), dOutlineScale: ValueCell.create(1), @@ -494,6 +496,13 @@ export class PostprocessingPass { gl.scissor(x, y, width, height); } + occlusionOffset: [x: number, y: number] = [0, 0]; + setOcclusionOffset(x: number, y: number) { + this.occlusionOffset[0] = x; + this.occlusionOffset[1] = y; + ValueCell.update(this.renderable.values.uOcclusionOffset, Vec2.set(this.renderable.values.uOcclusionOffset.ref.value, x, y)); + } + render(camera: ICamera, toDrawingBuffer: boolean, transparentBackground: boolean, backgroundColor: Color, props: PostprocessingProps) { this.updateState(camera, transparentBackground, backgroundColor, props); @@ -502,15 +511,9 @@ export class PostprocessingPass { this.outlinesRenderable.render(); } - if (props.occlusion.name === 'on') { - const { x, y, width, height } = camera.viewport; - const sx = Math.floor(x * this.ssaoScale); - const sy = Math.floor(y * this.ssaoScale); - const sw = Math.ceil(width * this.ssaoScale); - const sh = Math.ceil(height * this.ssaoScale); - this.webgl.gl.viewport(sx, sy, sw, sh); - this.webgl.gl.scissor(sx, sy, sw, sh); - + // don't render occlusion if offset is given, + // which will reuse the existing occlusion + if (props.occlusion.name === 'on' && this.occlusionOffset[0] === 0 && this.occlusionOffset[1] === 0) { this.ssaoFramebuffer.bind(); this.ssaoRenderable.render(); @@ -519,9 +522,6 @@ export class PostprocessingPass { this.ssaoBlurSecondPassFramebuffer.bind(); this.ssaoBlurSecondPassRenderable.render(); - - this.webgl.gl.viewport(x, y, width, height); - this.webgl.gl.scissor(x, y, width, height); } if (toDrawingBuffer) { diff --git a/src/mol-gl/shader/postprocessing.frag.ts b/src/mol-gl/shader/postprocessing.frag.ts index 9a50f414352179a0f5e3da916ea961020628f650..aefe55452a3007003fbb9f0ffbdc5998fd854b49 100644 --- a/src/mol-gl/shader/postprocessing.frag.ts +++ b/src/mol-gl/shader/postprocessing.frag.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Áron Samuel Kovács <aron.kovacs@mail.muni.cz> @@ -24,8 +24,7 @@ uniform vec3 uFogColor; uniform vec3 uOutlineColor; uniform bool uTransparentBackground; -uniform float uOcclusionBias; -uniform float uOcclusionRadius; +uniform vec2 uOcclusionOffset; uniform float uMaxPossibleViewZDiff; @@ -102,7 +101,7 @@ void main(void) { if (!isBackground(depth)) { viewDist = abs(getViewZ(depth)); fogFactor = smoothstep(uFogNear, uFogFar, viewDist); - float occlusionFactor = getSsao(coords); + float occlusionFactor = getSsao(coords + uOcclusionOffset); if (!uTransparentBackground) { color.rgb = mix(mix(occlusionColor, uFogColor, fogFactor), color.rgb, occlusionFactor); } else {