From 6eced47c44eea2162f6456d3d044647c4dacd31f Mon Sep 17 00:00:00 2001 From: AlexandruPopovici Date: Mon, 17 Oct 2022 14:32:00 +0300 Subject: [PATCH] Implemented interpolating during frame accumulation between the dynamic SAO and the static AO. This makes the transition much more smooth and seamless than simply jumping straight to the static AO which begins accumulating from 0 --- .../shaders/speckle-apply-ao-frag.ts | 19 +++++++ .../shaders/speckle-apply-ao-vert.ts | 6 ++ .../{ApplySAOPass.ts => ApplyAOPass.ts} | 56 ++++++++++++++++--- .../viewer/src/modules/pipeline/Pipeline.ts | 10 +++- .../src/modules/pipeline/SpecklePass.ts | 3 + 5 files changed, 85 insertions(+), 9 deletions(-) create mode 100644 packages/viewer/src/modules/materials/shaders/speckle-apply-ao-frag.ts create mode 100644 packages/viewer/src/modules/materials/shaders/speckle-apply-ao-vert.ts rename packages/viewer/src/modules/pipeline/{ApplySAOPass.ts => ApplyAOPass.ts} (51%) diff --git a/packages/viewer/src/modules/materials/shaders/speckle-apply-ao-frag.ts b/packages/viewer/src/modules/materials/shaders/speckle-apply-ao-frag.ts new file mode 100644 index 000000000..c8e2b2211 --- /dev/null +++ b/packages/viewer/src/modules/materials/shaders/speckle-apply-ao-frag.ts @@ -0,0 +1,19 @@ +export const speckleApplyAoFrag = ` + uniform float opacity; + uniform sampler2D tDiffuse; + uniform sampler2D tDiffuseInterp; + varying vec2 vUv; + #if ACCUMULATE == 1 + uniform float frameIndex; + #endif + + void main() { + vec3 currentSample = texture2D( tDiffuse, vUv ).rgb; + vec3 interpSample = texture2D( tDiffuseInterp, vUv ).rgb; + #if ACCUMULATE == 1 + gl_FragColor.rgb = mix(interpSample, currentSample, frameIndex/float(NUM_FRAMES)); + #else + gl_FragColor.rgb = currentSample; + #endif + gl_FragColor.a = 1.; + }` diff --git a/packages/viewer/src/modules/materials/shaders/speckle-apply-ao-vert.ts b/packages/viewer/src/modules/materials/shaders/speckle-apply-ao-vert.ts new file mode 100644 index 000000000..7d241ade3 --- /dev/null +++ b/packages/viewer/src/modules/materials/shaders/speckle-apply-ao-vert.ts @@ -0,0 +1,6 @@ +export const speckleApplyAoVert = ` + varying vec2 vUv; + void main() { + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + }` diff --git a/packages/viewer/src/modules/pipeline/ApplySAOPass.ts b/packages/viewer/src/modules/pipeline/ApplyAOPass.ts similarity index 51% rename from packages/viewer/src/modules/pipeline/ApplySAOPass.ts rename to packages/viewer/src/modules/pipeline/ApplyAOPass.ts index a378f3c45..ad1ca0fd9 100644 --- a/packages/viewer/src/modules/pipeline/ApplySAOPass.ts +++ b/packages/viewer/src/modules/pipeline/ApplyAOPass.ts @@ -1,28 +1,43 @@ import { AddEquation, + Camera, CustomBlending, DstAlphaFactor, DstColorFactor, NoBlending, + Scene, ShaderMaterial, Texture, - UniformsUtils, ZeroFactor } from 'three' import { FullScreenQuad, Pass } from 'three/examples/jsm/postprocessing/Pass' -import { CopyShader } from 'three/examples/jsm/shaders/CopyShader.js' -import { InputColorTextureUniform, SpecklePass } from './SpecklePass' +import { speckleApplyAoFrag } from '../materials/shaders/speckle-apply-ao-frag' +import { speckleApplyAoVert } from '../materials/shaders/speckle-apply-ao-vert' +import { Pipeline, RenderType } from './Pipeline' +import { + InputColorTextureUniform, + InputColorInterpolateTextureUniform, + SpeckleProgressivePass +} from './SpecklePass' -export class ApplySAOPass extends Pass implements SpecklePass { +export class ApplySAOPass extends Pass implements SpeckleProgressivePass { private fsQuad: FullScreenQuad public materialCopy: ShaderMaterial + private frameIndex = 0 constructor() { super() this.materialCopy = new ShaderMaterial({ - uniforms: UniformsUtils.clone(CopyShader.uniforms), - vertexShader: CopyShader.vertexShader, - fragmentShader: CopyShader.fragmentShader, + defines: { + ACCUMULATE: 0 + }, + uniforms: { + tDiffuse: { value: null }, + tDiffuseInterp: { value: null }, + frameIndex: { value: 0 } + }, + vertexShader: speckleApplyAoVert, + fragmentShader: speckleApplyAoFrag, blending: NoBlending }) this.materialCopy.transparent = true @@ -40,7 +55,10 @@ export class ApplySAOPass extends Pass implements SpecklePass { this.fsQuad = new FullScreenQuad(this.materialCopy) } - public setTexture(uName: InputColorTextureUniform, texture: Texture) { + public setTexture( + uName: InputColorTextureUniform | InputColorInterpolateTextureUniform, + texture: Texture + ) { this.materialCopy.uniforms[uName].value = texture this.materialCopy.needsUpdate = true } @@ -57,6 +75,28 @@ export class ApplySAOPass extends Pass implements SpecklePass { params } + setFrameIndex(index: number) { + this.frameIndex = index + } + + setRenderType(type: RenderType) { + if (type === RenderType.NORMAL) { + this.materialCopy.defines['ACCUMULATE'] = 0 + } else { + this.materialCopy.defines['ACCUMULATE'] = 1 + this.frameIndex = 0 + } + this.materialCopy.needsUpdate = true + } + + public update(scene: Scene, camera: Camera) { + scene + camera + this.materialCopy.defines['NUM_FRAMES'] = Pipeline.ACCUMULATE_FRAMES + this.materialCopy.uniforms['frameIndex'].value = this.frameIndex + this.materialCopy.needsUpdate = true + } + render(renderer, writeBuffer, readBuffer /*, deltaTime, maskActive*/) { writeBuffer readBuffer diff --git a/packages/viewer/src/modules/pipeline/Pipeline.ts b/packages/viewer/src/modules/pipeline/Pipeline.ts index 85bdf3e53..6a6d69d2d 100644 --- a/packages/viewer/src/modules/pipeline/Pipeline.ts +++ b/packages/viewer/src/modules/pipeline/Pipeline.ts @@ -3,7 +3,7 @@ import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js' import Batcher from '../batching/Batcher' import SpeckleRenderer from '../SpeckleRenderer' -import { ApplySAOPass } from './ApplySAOPass' +import { ApplySAOPass } from './ApplyAOPass' import { CopyOutputPass } from './CopyOutputPass' import { DepthPass } from './DepthPass' import { NormalsPass } from './NormalsPass' @@ -257,6 +257,7 @@ export class Pipeline { this.dynamicAoPass.setTexture('tDepth', this.depthPass.outputTexture) this.dynamicAoPass.setTexture('tNormal', this.normalsPass.outputTexture) this.applySaoPass.setTexture('tDiffuse', this.dynamicAoPass.outputTexture) + this.applySaoPass.setTexture('tDiffuseInterp', this.dynamicAoPass.outputTexture) this.staticAoPass.setTexture('tDepth', this.depthPass.outputTexture) let restoreVisibility @@ -288,7 +289,10 @@ export class Pipeline { this.dynamicAoPass.update(renderer.scene, renderer.camera) this.normalsPass.update(renderer.scene, renderer.camera) this.staticAoPass.update(renderer.scene, renderer.camera) + this.applySaoPass.update(renderer.scene, renderer.camera) + this.staticAoPass.setFrameIndex(this.accumulationFrame) + this.applySaoPass.setFrameIndex(this.accumulationFrame) } public render(): boolean { @@ -326,16 +330,20 @@ export class Pipeline { this.applySaoPass.enabled = true this.staticAoPass.enabled = true this.applySaoPass.setTexture('tDiffuse', this.staticAoPass.outputTexture) + this.applySaoPass.setTexture('tDiffuseInterp', this.dynamicAoPass.outputTexture) + this.applySaoPass.setRenderType(this.renderType) console.warn('Starting stationary') } public onStationaryEnd() { if (this.renderType === RenderType.NORMAL) return + this.accumulationFrame = 0 this.renderType = RenderType.NORMAL this.staticAoPass.enabled = false this.applySaoPass.enabled = true this.dynamicAoPass.enabled = true this.applySaoPass.setTexture('tDiffuse', this.dynamicAoPass.outputTexture) + this.applySaoPass.setRenderType(this.renderType) console.warn('Ending stationary') } } diff --git a/packages/viewer/src/modules/pipeline/SpecklePass.ts b/packages/viewer/src/modules/pipeline/SpecklePass.ts index 7dc2b2c9b..f014fbec0 100644 --- a/packages/viewer/src/modules/pipeline/SpecklePass.ts +++ b/packages/viewer/src/modules/pipeline/SpecklePass.ts @@ -1,8 +1,10 @@ import { Camera, Plane, Scene, Texture } from 'three' +import { RenderType } from './Pipeline' export type InputColorTextureUniform = 'tDiffuse' export type InputDepthTextureUniform = 'tDepth' export type InputNormalsTextureUniform = 'tNormal' +export type InputColorInterpolateTextureUniform = 'tDiffuseInterp' export interface SpecklePass { onBeforeRender?: () => void @@ -19,4 +21,5 @@ export interface SpecklePass { export interface SpeckleProgressivePass extends SpecklePass { setFrameIndex(index: number) + setRenderType?(type: RenderType) }