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) }