diff --git a/packages/viewer-sandbox/src/Sandbox.ts b/packages/viewer-sandbox/src/Sandbox.ts index 2718d3074..4a26bbc0e 100644 --- a/packages/viewer-sandbox/src/Sandbox.ts +++ b/packages/viewer-sandbox/src/Sandbox.ts @@ -32,6 +32,7 @@ export default class Sandbox { public static pipelineParams = { pipelineOutput: 8, + accumulationFrames: 16, dynamicAoEnabled: true, dynamicAoParams: { intensity: 1.25, @@ -43,6 +44,14 @@ export default class Sandbox { blurRadius: 4, blurStdDev: 4, blurDepthCutoff: 0.0007 + }, + staticAoEnabled: true, + staticAoParams: { + intensity: 1, + kernelRadius: 0.5, // World space + kernelSize: 16, + minDistance: 0, + maxDistance: 0.008 } } @@ -360,16 +369,30 @@ export default class Sandbox { this.viewer.getRenderer().pipelineOptions = Sandbox.pipelineParams this.viewer.requestRender() }) + + pipelineFolder + .addInput(Sandbox.pipelineParams, 'accumulationFrames', { + min: 1, + max: 128, + step: 1 + }) + .on('change', () => { + this.viewer.getRenderer().pipelineOptions = Sandbox.pipelineParams + this.viewer.requestRender() + }) + const dynamicAoFolder = pipelineFolder.addFolder({ title: 'Dynamic AO', expanded: true }) + dynamicAoFolder .addInput(Sandbox.pipelineParams.dynamicAoParams, 'intensity', { min: 0, max: 5 }) .on('change', () => { this.viewer.getRenderer().pipelineOptions = Sandbox.pipelineParams this.viewer.requestRender() }) + dynamicAoFolder .addInput(Sandbox.pipelineParams.dynamicAoParams, 'kernelRadius', { min: 0, @@ -379,6 +402,7 @@ export default class Sandbox { this.viewer.getRenderer().pipelineOptions = Sandbox.pipelineParams this.viewer.requestRender() }) + dynamicAoFolder .addInput(Sandbox.pipelineParams.dynamicAoParams, 'bias', { min: -1, @@ -429,40 +453,57 @@ export default class Sandbox { this.viewer.requestRender() }) - // postFolder - // .addInput(Sandbox.postParams, 'minDistance', { min: 0, max: 100, step: 0.000001 }) + const staticAoFolder = pipelineFolder.addFolder({ + title: 'Static AO', + expanded: true + }) + // staticAoFolder + // .addInput(Sandbox.pipelineParams, 'staticAoEnabled', {}) // .on('change', () => { - // this.viewer.getRenderer().pipelineOptions = Sandbox.postParams + // this.viewer.getRenderer().pipelineOptions = Sandbox.pipelineParams // this.viewer.requestRender() // }) + staticAoFolder + .addInput(Sandbox.pipelineParams.staticAoParams, 'minDistance', { + min: 0, + max: 100, + step: 0.000001 + }) + .on('change', () => { + this.viewer.getRenderer().pipelineOptions = Sandbox.pipelineParams + this.viewer.requestRender() + }) - // postFolder - // .addInput(Sandbox.postParams, 'maxDistance', { min: 0, max: 100, step: 0.000001 }) - // .on('change', () => { - // this.viewer.getRenderer().pipelineOptions = Sandbox.postParams - // this.viewer.requestRender() - // }) - // postFolder - // .addInput(Sandbox.postParams, 'ssaoKernelRadius', { min: 0, max: 100 }) - // .on('change', () => { - // this.viewer.getRenderer().pipelineOptions = Sandbox.postParams - // this.viewer.requestRender() - // }) - // postFolder.addInput(Sandbox.postParams, 'progressive', {}).on('change', () => { - // this.viewer.getRenderer().pipelineOptions = Sandbox.postParams - // this.viewer.requestRender() - // }) - // postFolder - // .addInput(Sandbox.postParams, 'progressiveAO', { - // options: { - // SAO: 0, - // SSAO: 1 - // } - // }) - // .on('change', () => { - // this.viewer.getRenderer().pipelineOptions = Sandbox.postParams - // this.viewer.requestRender() - // }) + staticAoFolder + .addInput(Sandbox.pipelineParams.staticAoParams, 'maxDistance', { + min: 0, + max: 100, + step: 0.000001 + }) + .on('change', () => { + this.viewer.getRenderer().pipelineOptions = Sandbox.pipelineParams + this.viewer.requestRender() + }) + staticAoFolder + .addInput(Sandbox.pipelineParams.staticAoParams, 'kernelRadius', { + min: 0, + max: 100 + }) + .on('change', () => { + this.viewer.getRenderer().pipelineOptions = Sandbox.pipelineParams + this.viewer.requestRender() + }) + + staticAoFolder + .addInput(Sandbox.pipelineParams.staticAoParams, 'kernelSize', { + min: 1, + max: 128, + step: 1 + }) + .on('change', () => { + this.viewer.getRenderer().pipelineOptions = Sandbox.pipelineParams + this.viewer.requestRender() + }) const lightsFolder = this.tabs.pages[1].addFolder({ title: 'Lights', diff --git a/packages/viewer-sandbox/src/main.ts b/packages/viewer-sandbox/src/main.ts index 067770572..1a1b0dcb8 100644 --- a/packages/viewer-sandbox/src/main.ts +++ b/packages/viewer-sandbox/src/main.ts @@ -80,9 +80,9 @@ sandbox.makeFilteringUI() // Load demo object await sandbox.loadUrl( - // 'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8?c=%5B-7.66134,10.82932,6.41935,-0.07739,-13.88552,1.8697,0,1%5D' + 'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8?c=%5B-7.66134,10.82932,6.41935,-0.07739,-13.88552,1.8697,0,1%5D' // Revit sample house (good for bim-like stuff with many display meshes) - 'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8' + // 'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8' // 'Super' heavy revit shit // 'https://speckle.xyz/streams/e6f9156405/commits/0694d53bb5' // Same sample revit house, local to dim's computer diff --git a/packages/viewer/src/modules/materials/shaders/speckle-static-ao-accumulate-frag.ts b/packages/viewer/src/modules/materials/shaders/speckle-static-ao-accumulate-frag.ts index 8b4298930..728582776 100644 --- a/packages/viewer/src/modules/materials/shaders/speckle-static-ao-accumulate-frag.ts +++ b/packages/viewer/src/modules/materials/shaders/speckle-static-ao-accumulate-frag.ts @@ -2,10 +2,10 @@ export const speckleStaticAoAccumulateFrag = /* glsl */ ` uniform float opacity; uniform sampler2D tDiffuse; varying vec2 vUv; - #define NUM_FRAMES 16 + // #define NUM_FRAMES 16 void main() { vec4 frameSample = texture2D( tDiffuse, vUv ); - gl_FragColor.xyz = (frameSample.rgb) * 1./float(NUM_FRAMES); + gl_FragColor.xyz = frameSample.rgb * 1./float(NUM_FRAMES); gl_FragColor.a = 1.;//*= opacity; }` diff --git a/packages/viewer/src/modules/materials/shaders/speckle-static-ao-generate-frag.ts b/packages/viewer/src/modules/materials/shaders/speckle-static-ao-generate-frag.ts index 8bfdd11ac..af007d73b 100644 --- a/packages/viewer/src/modules/materials/shaders/speckle-static-ao-generate-frag.ts +++ b/packages/viewer/src/modules/materials/shaders/speckle-static-ao-generate-frag.ts @@ -17,16 +17,17 @@ export const speckleStaticAoGenerateFrag = /* glsl */ ` uniform float minResolution; uniform float frameIndex; - #define KERNEL_SIZE 16 + #define AO_ESTIMATOR 1 + // #define KERNEL_SIZE 16 uniform sampler2D tNoise; uniform vec3 kernel[ KERNEL_SIZE ]; uniform float minDistance; uniform float maxDistance; - uniform float ssaoKernelRadius; #define NUM_SAMPLES 16 #define SPIRAL_TURNS 2 - #define NUM_FRAMES 16 + + // #define NUM_FRAMES 16 #define NORMAL_TEXTURE 0 #define IMPROVED_NORMAL_RECONSTRUCTION 0 @@ -210,35 +211,19 @@ export const speckleStaticAoGenerateFrag = /* glsl */ ` float sampleViewZ = getViewZ( sampleDepth ); vec3 sampleViewPosition = getViewPosition( sampleUv, sampleDepth, sampleViewZ ); + /** McGuire Estimator*/ vec3 v = sampleViewPosition - centerViewPosition; - float vv = dot(v, v); - float vn = dot(v, centerViewNormal);// - uBias; + float vn = dot(v, centerViewNormal) - bias; - // #if VARIATION == 0 - - // (from the HPG12 paper) // Note large epsilon to avoid overdarkening within cracks float radius2 = 2.;//uSampleRadiusWS * uSampleRadiusWS float epsilon = 0.01; - // occlusionSum += float(vv < radius2) * max(vn / (epsilon + vv), 0.0) / 4.; - // #elif VARIATION == 1 // default / recommended - - // Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended] float f = max(radius2 - vv, 0.0) / radius2; occlusionSum += f * f * f * max(vn / (epsilon + vv), 0.0) / 4.; - - // #elif VARIATION == 2 - - // // Medium contrast (which looks better at high radii), no division. Note that the - // // contribution still falls off with radius^2, but we've adjusted the rate in a way that is - // // more computationally efficient and happens to be aesthetically pleasing. - // float invRadius2 = 1.0 / radius2; - // return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn, 0.0); - - + /** Three.js SAO Estimator*/ // vec3 viewDelta = sampleViewPosition - centerViewPosition; // float viewDistance = length( viewDelta ); // float scaledScreenDistance = scaleDividedByCameraFar * viewDistance; @@ -259,7 +244,7 @@ export const speckleStaticAoGenerateFrag = /* glsl */ ` float occlusion = 0.0; for ( int i = 0; i < KERNEL_SIZE; i ++ ) { vec3 sampleVector = kernelMatrix * kernel[ i ]; // reorient sample vector in view space - vec3 samplePoint = viewPosition + ( sampleVector * ssaoKernelRadius ); // calculate sample point + vec3 samplePoint = viewPosition + ( sampleVector * kernelRadius ); // calculate sample point vec4 samplePointNDC = cameraProjectionMatrix * vec4( samplePoint, 1.0 ); // project point and calculate NDC samplePointNDC /= samplePointNDC.w; vec2 samplePointUv = samplePointNDC.xy * 0.5 + 0.5; // compute uv coordinates diff --git a/packages/viewer/src/modules/pipeline/DynamicAOPass.ts b/packages/viewer/src/modules/pipeline/DynamicAOPass.ts index 68eae83ce..a1da743ea 100644 --- a/packages/viewer/src/modules/pipeline/DynamicAOPass.ts +++ b/packages/viewer/src/modules/pipeline/DynamicAOPass.ts @@ -47,7 +47,7 @@ export interface DynamicAOPassParams { blurDepthCutoff: number } -export const DefaultSpeckleDynamicSAOPassParams = { +export const DefaultDynamicAOPassParams = { intensity: 1.25, scale: 0, kernelRadius: 10, @@ -60,7 +60,7 @@ export const DefaultSpeckleDynamicSAOPassParams = { } export class DynamicSAOPass extends Pass implements SpecklePass { - private params: DynamicAOPassParams = DefaultSpeckleDynamicSAOPassParams + private params: DynamicAOPassParams = DefaultDynamicAOPassParams private colorBuffer: Color = new Color() private saoMaterial: ShaderMaterial = null private vBlurMaterial: ShaderMaterial = null diff --git a/packages/viewer/src/modules/pipeline/Pipeline.ts b/packages/viewer/src/modules/pipeline/Pipeline.ts index 4b4e8c1e9..8257944e4 100644 --- a/packages/viewer/src/modules/pipeline/Pipeline.ts +++ b/packages/viewer/src/modules/pipeline/Pipeline.ts @@ -8,14 +8,22 @@ import { CopyOutputPass } from './CopyOutputPass' import { DepthPass } from './DepthPass' import { NormalsPass } from './NormalsPass' import { - DefaultSpeckleDynamicSAOPassParams, + DefaultDynamicAOPassParams, DynamicSAOPass, DynamicAOOutputType, DynamicAOPassParams, NormalsType } from './DynamicAOPass' -// import { SpecklePass } from './SpecklePass' -// import { SpeckleStaticAOGeneratePass } from './SpeckleStaticAOGeneratePass' +import { + DefaultStaticAoPassParams, + StaticAOPass, + StaticAoPassParams +} from './StaticAOPass' + +export enum RenderType { + NORMAL, + ACCUMULATION +} export enum PipelineOutputType { DEPTH_RGBA = 0, @@ -31,24 +39,25 @@ export enum PipelineOutputType { export interface PipelineOptions { pipelineOutput: PipelineOutputType + accumulationFrames: number dynamicAoEnabled: boolean dynamicAoParams: DynamicAOPassParams + staticAoEnabled: boolean + staticAoParams: StaticAoPassParams } export const DefaultPipelineOptions: PipelineOptions = { pipelineOutput: PipelineOutputType.FINAL, + accumulationFrames: 16, dynamicAoEnabled: true, - dynamicAoParams: DefaultSpeckleDynamicSAOPassParams - // saoScaleOffset: 0, - // saoNormalsRendering: NormalsType.ACCURATE, - // minDistance: 0, - // maxDistance: 0.008, - // ssaoKernelRadius: 0.5, - // progressiveAO: 0, - // progressive: true + dynamicAoParams: DefaultDynamicAOPassParams, + staticAoEnabled: true, + staticAoParams: DefaultStaticAoPassParams } export class Pipeline { + public static ACCUMULATE_FRAMES = 16 + private _renderer: WebGLRenderer = null private _batcher: Batcher = null private _pipelineOptions: PipelineOptions = Object.assign({}, DefaultPipelineOptions) @@ -61,7 +70,11 @@ export class Pipeline { private applySaoPass: ApplySAOPass = null private copyOutputPass: CopyOutputPass = null + private staticAoPass: StaticAOPass = null + private drawingSize: Vector2 = new Vector2() + private renderType: RenderType = RenderType.NORMAL + private accumulationFrame = 0 public set pipelineOptions(options: Partial) { Object.assign(this._pipelineOptions, options) @@ -82,6 +95,9 @@ export class Pipeline { this.renderPass.enabled = true } this.dynamicAoPass.setParams(options.dynamicAoParams) + this.staticAoPass.setParams(options.staticAoParams) + this.accumulationFrame = 0 + Pipeline.ACCUMULATE_FRAMES = options.accumulationFrames this.pipelineOutput = options.pipelineOutput } @@ -188,6 +204,19 @@ export class Pipeline { this.copyOutputPass.setOutputType(PipelineOutputType.COLOR) this.dynamicAoPass.setOutputType(DynamicAOOutputType.AO_BLURRED) break + + case PipelineOutputType.PROGRESSIVE_AO: + this.depthPass.enabled = true + this.normalsPass.enabled = false + this.dynamicAoPass.enabled = false + this.renderPass.enabled = false + this.applySaoPass.enabled = false + this.staticAoPass.enabled = true + this.copyOutputPass.enabled = true + this.applySaoPass.setTexture('tDiffuse', this.staticAoPass.outputTexture) + this.copyOutputPass.setTexture('tDiffuse', this.staticAoPass.outputTexture) + this.copyOutputPass.setOutputType(PipelineOutputType.COLOR) + break default: break } @@ -210,12 +239,17 @@ export class Pipeline { this.renderPass.renderToScreen = true this.applySaoPass = new ApplySAOPass() this.applySaoPass.renderToScreen = true + + this.staticAoPass = new StaticAOPass() + this.staticAoPass.enabled = false + this.copyOutputPass = new CopyOutputPass() this.copyOutputPass.renderToScreen = true this.copyOutputPass.enabled = false this.composer.addPass(this.depthPass) this.composer.addPass(this.normalsPass) this.composer.addPass(this.dynamicAoPass) + this.composer.addPass(this.staticAoPass) this.composer.addPass(this.renderPass) this.composer.addPass(this.applySaoPass) this.composer.addPass(this.copyOutputPass) @@ -223,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.staticAoPass.setTexture('tDepth', this.depthPass.outputTexture) let restoreVisibility this.depthPass.onBeforeRender = () => { @@ -252,6 +287,8 @@ export class Pipeline { this.depthPass.update(renderer.scene, renderer.camera) this.dynamicAoPass.update(renderer.scene, renderer.camera) this.normalsPass.update(renderer.scene, renderer.camera) + this.staticAoPass.update(renderer.scene, renderer.camera) + this.staticAoPass.setFrameIndex(this.accumulationFrame) } public render(): boolean { @@ -259,8 +296,15 @@ export class Pipeline { if (this.drawingSize.length() === 0) return this._renderer.clear(true) - this.composer.render() - return true + if (this.renderType === RenderType.NORMAL) { + this.composer.render() + return true + } else { + console.warn('Rendering accumulation frame -> ', this.accumulationFrame) + this.composer.render() + this.accumulationFrame++ + return this.accumulationFrame < Pipeline.ACCUMULATE_FRAMES + } } public resize(width: number, height: number) { @@ -268,15 +312,24 @@ export class Pipeline { } public onStationaryBegin() { - // this.renderType = RenderType.ACCUMULATION - // this.staticAOGenerationPass.enabled = true - // this.accumulationFrame = 0 + this.renderType = RenderType.ACCUMULATION + this.accumulationFrame = 0 + this.depthPass.enabled = true + this.normalsPass.enabled = false + this.dynamicAoPass.enabled = false + this.renderPass.enabled = true + this.applySaoPass.enabled = true + this.staticAoPass.enabled = true + this.applySaoPass.setTexture('tDiffuse', this.staticAoPass.outputTexture) console.warn('Starting stationary') } public onStationaryEnd() { - // this.renderType = RenderType.NORMAL - // this.staticAOGenerationPass.enabled = false + this.renderType = RenderType.NORMAL + this.staticAoPass.enabled = false + this.applySaoPass.enabled = true + this.dynamicAoPass.enabled = true + this.applySaoPass.setTexture('tDiffuse', this.dynamicAoPass.outputTexture) console.warn('Ending stationary') } } diff --git a/packages/viewer/src/modules/pipeline/SpecklePass.ts b/packages/viewer/src/modules/pipeline/SpecklePass.ts index bc71e494e..7dc2b2c9b 100644 --- a/packages/viewer/src/modules/pipeline/SpecklePass.ts +++ b/packages/viewer/src/modules/pipeline/SpecklePass.ts @@ -16,3 +16,7 @@ export interface SpecklePass { setParams?(params: unknown) setClippingPlanes?(planes: Plane[]) } + +export interface SpeckleProgressivePass extends SpecklePass { + setFrameIndex(index: number) +} diff --git a/packages/viewer/src/modules/pipeline/SpeckleStaticAOGeneratePass.ts b/packages/viewer/src/modules/pipeline/StaticAOPass.ts similarity index 73% rename from packages/viewer/src/modules/pipeline/SpeckleStaticAOGeneratePass.ts rename to packages/viewer/src/modules/pipeline/StaticAOPass.ts index 315ed41b0..96eace04d 100644 --- a/packages/viewer/src/modules/pipeline/SpeckleStaticAOGeneratePass.ts +++ b/packages/viewer/src/modules/pipeline/StaticAOPass.ts @@ -14,6 +14,7 @@ import { RedFormat, RepeatWrapping, ReverseSubtractEquation, + Scene, ShaderMaterial, Texture, Vector2, @@ -23,61 +24,76 @@ import { } from 'three' import { FullScreenQuad, Pass } from 'three/examples/jsm/postprocessing/Pass' -import Batcher from '../batching/Batcher' import { speckleStaticAoGenerateVert } from '../materials/shaders/speckle-static-ao-generate-vert' import { speckleStaticAoGenerateFrag } from '../materials/shaders/speckle-static-ao-generate-frag' import { speckleStaticAoAccumulateVert } from '../materials/shaders/speckle-static-ao-accumulate-vert' import { speckleStaticAoAccumulateFrag } from '../materials/shaders/speckle-static-ao-accumulate-frag' import { SimplexNoise } from 'three/examples/jsm//math/SimplexNoise.js' +import { + InputDepthTextureUniform, + InputNormalsTextureUniform, + SpeckleProgressivePass +} from './SpecklePass' +import { Pipeline } from './Pipeline' /** * SAO implementation inspired from bhouston previous SAO work */ -export class SpeckleStaticAOGeneratePass extends Pass { - private batcher: Batcher = null +export interface StaticAoPassParams { + intensity: number + kernelRadius: number + kernelSize: number + minDistance: number + maxDistance: number +} + +export const DefaultStaticAoPassParams = { + intensity: 1, + kernelRadius: 0.5, // World space + kernelSize: 16, + minDistance: 0, + maxDistance: 0.008 +} + +export class StaticAOPass extends Pass implements SpeckleProgressivePass { public aoMaterial: ShaderMaterial = null private accumulateMaterial: ShaderMaterial = null - private _depthTexture: Texture - private _normalTexture: Texture private _generationBuffer: WebGLRenderTarget private _accumulationBuffer: WebGLRenderTarget + private params: StaticAoPassParams = DefaultStaticAoPassParams private fsQuad: FullScreenQuad private frameIndex = 0 - private kernels: Array> = new Array(16) - private kernelSize = 16 + private kernels: Array> = [] private noiseTextures: Array = [] - public minDistance = 0.02 - public maxDistance = 0.3 - public ssaoKernelRadius = 1 - public progressiveAO = 0 - public kernelRadius = 15 - public set depthTexture(value: Texture) { - this._depthTexture = value - this.aoMaterial.uniforms['tDepth'].value = value + public setTexture( + uName: InputDepthTextureUniform | InputNormalsTextureUniform, + texture: Texture + ) { + if (uName === 'tDepth') { + this.aoMaterial.uniforms['tDepth'].value = texture + } + if (uName === 'tNormal') { + this.aoMaterial.uniforms['tNormal'].value = texture + } this.aoMaterial.needsUpdate = true } - public set normalTexture(value: Texture) { - this._normalTexture = value - } - public get outputTexture() { - return this._accumulationBuffer + return this._accumulationBuffer.texture } - constructor(batcher: Batcher) { + public get displayName(): string { + return 'STATIC-AO' + } + + constructor() { super() - this.batcher = batcher this._generationBuffer = new WebGLRenderTarget(256, 256) this._accumulationBuffer = new WebGLRenderTarget(256, 256) - const aoDefines = { - AO_ESTIMATOR: 0 - } this.aoMaterial = new ShaderMaterial({ - defines: aoDefines, fragmentShader: speckleStaticAoGenerateFrag, vertexShader: speckleStaticAoGenerateVert, uniforms: { @@ -95,16 +111,14 @@ export class SpeckleStaticAOGeneratePass extends Pass { bias: { value: 0 }, minResolution: { value: 0.0 }, - kernelRadius: { value: 15.0 }, - randomSeed: { value: 0.0 }, + kernelRadius: { value: 0.5 }, // World space frameIndex: { value: 0 }, tNoise: { value: null }, kernel: { value: null }, minDistance: { value: 0.0 }, - maxDistance: { value: 0.008 }, - ssaoKernelRadius: { value: 0.5 } + maxDistance: { value: 1 } } }) @@ -133,7 +147,26 @@ export class SpeckleStaticAOGeneratePass extends Pass { this.fsQuad = new FullScreenQuad(this.aoMaterial) } - public update(camera: Camera, frameIndex: number) { + public setParams(params: unknown) { + Object.assign(this.params, params) + this.kernels = [] + this.noiseTextures = [] + } + + public setFrameIndex(index: number) { + this.frameIndex = index + } + + public update(scene: Scene, camera: Camera) { + /** DEFINES */ + this.aoMaterial.defines['PERSPECTIVE_CAMERA'] = (camera as PerspectiveCamera) + .isPerspectiveCamera + ? 1 + : 0 + this.aoMaterial.defines['NUM_FRAMES'] = Pipeline.ACCUMULATE_FRAMES + this.aoMaterial.defines['KERNEL_SIZE'] = this.params.kernelSize + this.accumulateMaterial.defines['NUM_FRAMES'] = Pipeline.ACCUMULATE_FRAMES + /** UNIFORMS */ this.aoMaterial.uniforms['cameraNear'].value = ( camera as PerspectiveCamera | OrthographicCamera ).near @@ -146,29 +179,22 @@ export class SpeckleStaticAOGeneratePass extends Pass { this.aoMaterial.uniforms['cameraProjectionMatrix'].value.copy( camera.projectionMatrix ) - this.aoMaterial.uniforms['scale'].value = ( - camera as PerspectiveCamera | OrthographicCamera - ).far - this.aoMaterial.defines['PERSPECTIVE_CAMERA'] = (camera as PerspectiveCamera) - .isPerspectiveCamera - ? 1 - : 0 - this.aoMaterial.uniforms['kernelRadius'].value = this.kernelRadius - this.aoMaterial.uniforms['frameIndex'].value = frameIndex - this.frameIndex = frameIndex + if (!this.kernels[this.frameIndex]) { + this.generateSampleKernel(this.frameIndex) + } + if (!this.noiseTextures[this.frameIndex]) { + this.generateRandomKernelRotations(this.frameIndex) + } + this.aoMaterial.uniforms['kernel'].value = this.kernels[this.frameIndex] + this.aoMaterial.uniforms['tNoise'].value = this.noiseTextures[this.frameIndex] - if (!this.kernels[frameIndex]) { - this.generateSampleKernel(frameIndex) - } - if (!this.noiseTextures[frameIndex]) { - this.generateRandomKernelRotations(frameIndex) - } - this.aoMaterial.uniforms['kernel'].value = this.kernels[frameIndex] - this.aoMaterial.uniforms['tNoise'].value = this.noiseTextures[frameIndex] - this.aoMaterial.uniforms['ssaoKernelRadius'].value = this.ssaoKernelRadius - this.aoMaterial.uniforms['minDistance'].value = this.minDistance - this.aoMaterial.uniforms['maxDistance'].value = this.maxDistance + this.aoMaterial.uniforms['kernelRadius'].value = this.params.kernelRadius + this.aoMaterial.uniforms['frameIndex'].value = this.frameIndex + + this.aoMaterial.uniforms['minDistance'].value = this.params.minDistance + this.aoMaterial.uniforms['maxDistance'].value = this.params.maxDistance this.aoMaterial.needsUpdate = true + this.accumulateMaterial.needsUpdate = true } public render(renderer, writeBuffer, readBuffer) { @@ -192,7 +218,7 @@ export class SpeckleStaticAOGeneratePass extends Pass { renderer.autoClear = false renderer.setClearColor(0x000000) renderer.setClearAlpha(1) - renderer.clear() + renderer.clear(true) this.fsQuad.material = this.aoMaterial this.fsQuad.render(renderer) @@ -200,8 +226,9 @@ export class SpeckleStaticAOGeneratePass extends Pass { if (this.frameIndex === 0) { renderer.setClearColor(0xffffff) renderer.setClearAlpha(1) - renderer.clear() + renderer.clear(true) } + this.fsQuad.material = this.accumulateMaterial this.fsQuad.render(renderer) } @@ -215,7 +242,7 @@ export class SpeckleStaticAOGeneratePass extends Pass { } private generateSampleKernel(frameIndex: number) { - const kernelSize = this.kernelSize + const kernelSize = this.params.kernelSize this.kernels[frameIndex] = [] for (let i = 0; i < kernelSize; i++) {