diff --git a/packages/viewer-sandbox/src/Sandbox.ts b/packages/viewer-sandbox/src/Sandbox.ts index 1dadd4c7e..2718d3074 100644 --- a/packages/viewer-sandbox/src/Sandbox.ts +++ b/packages/viewer-sandbox/src/Sandbox.ts @@ -360,96 +360,74 @@ export default class Sandbox { this.viewer.getRenderer().pipelineOptions = Sandbox.pipelineParams this.viewer.requestRender() }) - // postFolder - // .addInput(Sandbox.postParams, 'saoEnabled', { label: 'SAO-ENABLED' }) - // .on('change', () => { - // this.viewer.getRenderer().pipelineOptions = Sandbox.postParams - // this.viewer.requestRender() - // }) - // postFolder - // .addInput(Sandbox.postParams.saoParams, 'saoBias', { - // min: -1, - // max: 1 - // }) - // .on('change', () => { - // this.viewer.getRenderer().pipelineOptions = Sandbox.postParams - // this.viewer.requestRender() - // }) - // postFolder - // .addInput(Sandbox.postParams.saoParams, 'saoIntensity', { - // min: 0, - // max: 5 - // }) - // .on('change', () => { - // this.viewer.getRenderer().pipelineOptions = Sandbox.postParams - // 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, + max: 500 + }) + .on('change', () => { + this.viewer.getRenderer().pipelineOptions = Sandbox.pipelineParams + this.viewer.requestRender() + }) + dynamicAoFolder + .addInput(Sandbox.pipelineParams.dynamicAoParams, 'bias', { + min: -1, + max: 1 + }) + .on('change', () => { + this.viewer.getRenderer().pipelineOptions = Sandbox.pipelineParams + this.viewer.requestRender() + }) + dynamicAoFolder + .addInput(Sandbox.pipelineParams.dynamicAoParams, 'normalsType', { + options: { + DEFAULT: 0, + ADVANCED: 1, + ACCURATE: 2 + } + }) + .on('change', () => { + this.viewer.getRenderer().pipelineOptions = Sandbox.pipelineParams + this.viewer.requestRender() + }) - // // postFolder - // // .addInput(Sandbox.postParams.saoParams, 'saoScale', { - // // min: 0, - // // max: 100 - // // }) - // // .on('change', () => { - // // this.viewer.getRenderer().pipelineOptions = Sandbox.postParams - // // this.viewer.requestRender() - // // }) - // postFolder - // .addInput(Sandbox.postParams, 'saoScaleOffset', { - // min: -100, - // max: 100 - // }) - // .on('change', () => { - // this.viewer.getRenderer().pipelineOptions = Sandbox.postParams - // this.viewer.requestRender() - // }) + dynamicAoFolder + .addInput(Sandbox.pipelineParams.dynamicAoParams, 'blurEnabled', {}) + .on('change', () => { + this.viewer.getRenderer().pipelineOptions = Sandbox.pipelineParams + this.viewer.requestRender() + }) - // postFolder - // .addInput(Sandbox.postParams, 'saoNormalsRendering', { - // options: { - // DEFAULT: 0, - // ADVANCED: 1, - // ACCURATE: 2 - // } - // }) - // .on('change', () => { - // this.viewer.getRenderer().pipelineOptions = Sandbox.postParams - // this.viewer.requestRender() - // }) + dynamicAoFolder + .addInput(Sandbox.pipelineParams.dynamicAoParams, 'blurRadius', { + min: 0, + max: 10 + }) + .on('change', () => { + this.viewer.getRenderer().pipelineOptions = Sandbox.pipelineParams + this.viewer.requestRender() + }) - // postFolder - // .addInput(Sandbox.postParams.saoParams, 'saoKernelRadius', { - // min: 0, - // max: 100 - // }) - // .on('change', () => { - // this.viewer.getRenderer().pipelineOptions = Sandbox.postParams - // this.viewer.requestRender() - // }) - - // // postFolder - // // .addInput(Sandbox.postParams.saoParams, 'saoMinResolution', { - // // min: 0, - // // max: 1 - // // }) - // // .on('change', () => { - // // this.viewer.getRenderer().pipelineOptions = Sandbox.postParams - // // this.viewer.requestRender() - // // }) - - // postFolder - // .addInput(Sandbox.postParams.saoParams, 'saoBlur', {}) - // .on('change', () => { - // this.viewer.getRenderer().pipelineOptions = Sandbox.postParams - // this.viewer.requestRender() - // }) - - // postFolder - // .addInput(Sandbox.postParams.saoParams, 'saoBlurRadius', { min: 0, max: 10 }) - // .on('change', () => { - // this.viewer.getRenderer().pipelineOptions = Sandbox.postParams - // this.viewer.requestRender() - // }) + dynamicAoFolder + .addInput(Sandbox.pipelineParams.dynamicAoParams, 'blurDepthCutoff', { + min: 0, + max: 1, + step: 0.00001 + }) + .on('change', () => { + this.viewer.getRenderer().pipelineOptions = Sandbox.pipelineParams + this.viewer.requestRender() + }) // postFolder // .addInput(Sandbox.postParams, 'minDistance', { min: 0, max: 100, step: 0.000001 }) @@ -486,26 +464,6 @@ export default class Sandbox { // this.viewer.requestRender() // }) - // postFolder - // .addInput(Sandbox.postParams.saoParams, 'saoBlurStdDev', { - // min: 0, - // max: 150 - // }) - // .on('change', () => { - // this.viewer.getRenderer().pipelineOptions = Sandbox.postParams - // this.viewer.requestRender() - // }) - - // postFolder - // .addInput(Sandbox.postParams.saoParams, 'saoBlurDepthCutoff', { - // min: 0, - // max: 10 - // }) - // .on('change', () => { - // this.viewer.getRenderer().pipelineOptions = Sandbox.postParams - // this.viewer.requestRender() - // }) - const lightsFolder = this.tabs.pages[1].addFolder({ title: 'Lights', expanded: true diff --git a/packages/viewer/src/modules/pipeline/DynamicSAOPass.ts b/packages/viewer/src/modules/pipeline/DynamicAOPass.ts similarity index 87% rename from packages/viewer/src/modules/pipeline/DynamicSAOPass.ts rename to packages/viewer/src/modules/pipeline/DynamicAOPass.ts index d29490af6..68eae83ce 100644 --- a/packages/viewer/src/modules/pipeline/DynamicSAOPass.ts +++ b/packages/viewer/src/modules/pipeline/DynamicAOPass.ts @@ -17,7 +17,11 @@ import { speckleSaoVert } from '../materials/shaders/speckle-sao-vert' import { SAOShader } from 'three/examples/jsm/shaders/SAOShader.js' import { DepthLimitedBlurShader } from 'three/examples/jsm/shaders/DepthLimitedBlurShader.js' import { BlurShaderUtils } from 'three/examples/jsm/shaders/DepthLimitedBlurShader.js' -import { InputDepthTextureUniform, SpecklePass } from './SpecklePass' +import { + InputDepthTextureUniform, + InputNormalsTextureUniform, + SpecklePass +} from './SpecklePass' export enum NormalsType { DEFAULT = 0, @@ -25,7 +29,13 @@ export enum NormalsType { ACCURATE = 2 } -export interface SpeckleDynamicSAOPassParams { +export enum DynamicAOOutputType { + RECONSTRUCTED_NORMALS, + AO, + AO_BLURRED +} + +export interface DynamicAOPassParams { intensity: number scale: number kernelRadius: number @@ -50,7 +60,7 @@ export const DefaultSpeckleDynamicSAOPassParams = { } export class DynamicSAOPass extends Pass implements SpecklePass { - private params: SpeckleDynamicSAOPassParams = DefaultSpeckleDynamicSAOPassParams + private params: DynamicAOPassParams = DefaultSpeckleDynamicSAOPassParams private colorBuffer: Color = new Color() private saoMaterial: ShaderMaterial = null private vBlurMaterial: ShaderMaterial = null @@ -58,6 +68,7 @@ export class DynamicSAOPass extends Pass implements SpecklePass { private saoRenderTarget: WebGLRenderTarget = null private blurIntermediateRenderTarget: WebGLRenderTarget = null private fsQuad: FullScreenQuad = null + private _outputType: DynamicAOOutputType = DynamicAOOutputType.AO_BLURRED private prevStdDev: number private prevNumSamples: number @@ -70,11 +81,6 @@ export class DynamicSAOPass extends Pass implements SpecklePass { return this.saoRenderTarget.texture } - public set outputReconstructedNormals(value: boolean) { - if (value) this.saoMaterial.defines['OUTPUT_RECONSTRUCTED_NORMALS'] = '' - else delete this.saoMaterial.defines['OUTPUT_RECONSTRUCTED_NORMALS'] - } - constructor() { super() @@ -135,16 +141,34 @@ export class DynamicSAOPass extends Pass implements SpecklePass { Object.assign(this.params, params) } - public setTexture(uName: InputDepthTextureUniform, texture: Texture) { - this.saoMaterial.uniforms['tDepth'].value = texture - this.vBlurMaterial.uniforms['tDepth'].value = texture - this.hBlurMaterial.uniforms['tDepth'].value = texture + public setOutputType(type: DynamicAOOutputType) { + this._outputType = type + } + + public setTexture( + uName: InputDepthTextureUniform | InputNormalsTextureUniform, + texture: Texture + ) { + if (uName === 'tDepth') { + this.saoMaterial.uniforms['tDepth'].value = texture + this.vBlurMaterial.uniforms['tDepth'].value = texture + this.hBlurMaterial.uniforms['tDepth'].value = texture + } + if (uName === 'tNormal') { + this.saoMaterial.uniforms['tNormal'].value = texture + } this.saoMaterial.needsUpdate = true this.vBlurMaterial.needsUpdate = true this.hBlurMaterial.needsUpdate = true } public update(scene: Scene, camera: Camera) { + if (this._outputType === DynamicAOOutputType.RECONSTRUCTED_NORMALS) { + this.saoMaterial.defines['OUTPUT_RECONSTRUCTED_NORMALS'] = '' + } else { + delete this.saoMaterial.defines['OUTPUT_RECONSTRUCTED_NORMALS'] + } + this.params.scale = (camera as PerspectiveCamera | OrthographicCamera).far /** SAO DEFINES */ this.saoMaterial.defines['PERSPECTIVE_CAMERA'] = (camera as PerspectiveCamera) @@ -236,8 +260,6 @@ export class DynamicSAOPass extends Pass implements SpecklePass { } public render(renderer) { - const outputNormals = - this.saoMaterial.defines['OUTPUT_RECONSTRUCTED_NORMALS'] !== undefined // Rendering SAO texture renderer.getClearColor(this.colorBuffer) const originalClearAlpha = renderer.getClearAlpha() @@ -253,7 +275,10 @@ export class DynamicSAOPass extends Pass implements SpecklePass { this.fsQuad.material = this.saoMaterial this.fsQuad.render(renderer) - if (this.params.blurEnabled && !outputNormals) { + if ( + this.params.blurEnabled && + this._outputType === DynamicAOOutputType.AO_BLURRED + ) { renderer.setRenderTarget(this.blurIntermediateRenderTarget) renderer.setClearColor(0xffffff) renderer.setClearAlpha(1.0) diff --git a/packages/viewer/src/modules/pipeline/Pipeline.ts b/packages/viewer/src/modules/pipeline/Pipeline.ts index db2dc1a0e..4b4e8c1e9 100644 --- a/packages/viewer/src/modules/pipeline/Pipeline.ts +++ b/packages/viewer/src/modules/pipeline/Pipeline.ts @@ -10,8 +10,10 @@ import { NormalsPass } from './NormalsPass' import { DefaultSpeckleDynamicSAOPassParams, DynamicSAOPass, - SpeckleDynamicSAOPassParams -} from './DynamicSAOPass' + DynamicAOOutputType, + DynamicAOPassParams, + NormalsType +} from './DynamicAOPass' // import { SpecklePass } from './SpecklePass' // import { SpeckleStaticAOGeneratePass } from './SpeckleStaticAOGeneratePass' @@ -30,7 +32,7 @@ export enum PipelineOutputType { export interface PipelineOptions { pipelineOutput: PipelineOutputType dynamicAoEnabled: boolean - dynamicAoParams: SpeckleDynamicSAOPassParams + dynamicAoParams: DynamicAOPassParams } export const DefaultPipelineOptions: PipelineOptions = { @@ -63,12 +65,46 @@ export class Pipeline { public set pipelineOptions(options: Partial) { Object.assign(this._pipelineOptions, options) - this.pipelineOutput = options.pipelineOutput + if (options.dynamicAoEnabled) { + this.dynamicAoPass.enabled = true + this.renderPass.enabled = true + this.applySaoPass.enabled = true + this.normalsPass.enabled = + options.dynamicAoParams.normalsType === NormalsType.DEFAULT ? true : false + this.depthPass.enabled = true + this.copyOutputPass.enabled = false + } else { + this.depthPass.enabled = false + this.dynamicAoPass.enabled = false + this.applySaoPass.enabled = false + this.copyOutputPass.enabled = false + this.normalsPass.enabled = false + this.renderPass.enabled = true + } this.dynamicAoPass.setParams(options.dynamicAoParams) + + this.pipelineOutput = options.pipelineOutput } public set pipelineOutput(outputType: PipelineOutputType) { switch (outputType) { + case PipelineOutputType.FINAL: + this.dynamicAoPass.enabled = true + this.renderPass.enabled = true + this.applySaoPass.enabled = true + this.normalsPass.enabled = + this._pipelineOptions.dynamicAoParams.normalsType === NormalsType.DEFAULT + ? true + : false + this.depthPass.enabled = true + this.copyOutputPass.enabled = false + this.dynamicAoPass.setOutputType( + this._pipelineOptions.dynamicAoParams.blurEnabled + ? DynamicAOOutputType.AO_BLURRED + : DynamicAOOutputType.AO + ) + break + case PipelineOutputType.DEPTH_RGBA: this.dynamicAoPass.enabled = false this.renderPass.enabled = false @@ -120,7 +156,37 @@ export class Pipeline { this.copyOutputPass.enabled = true this.copyOutputPass.setTexture('tDiffuse', this.dynamicAoPass.outputTexture) this.copyOutputPass.setOutputType(PipelineOutputType.GEOMETRY_NORMALS) - this.dynamicAoPass.outputReconstructedNormals = true + this.dynamicAoPass.setOutputType(DynamicAOOutputType.RECONSTRUCTED_NORMALS) + break + + case PipelineOutputType.DYNAMIC_AO: + this.depthPass.enabled = true + this.dynamicAoPass.enabled = true + this.applySaoPass.enabled = false + this.renderPass.enabled = false + this.normalsPass.enabled = + this._pipelineOptions.dynamicAoParams.normalsType === NormalsType.DEFAULT + ? true + : false + this.copyOutputPass.enabled = true + this.copyOutputPass.setTexture('tDiffuse', this.dynamicAoPass.outputTexture) + this.copyOutputPass.setOutputType(PipelineOutputType.COLOR) + this.dynamicAoPass.setOutputType(DynamicAOOutputType.AO) + break + + case PipelineOutputType.DYNAMIC_AO_BLURED: + this.depthPass.enabled = true + this.dynamicAoPass.enabled = true + this.applySaoPass.enabled = false + this.renderPass.enabled = false + this.normalsPass.enabled = + this._pipelineOptions.dynamicAoParams.normalsType === NormalsType.DEFAULT + ? true + : false + this.copyOutputPass.enabled = true + this.copyOutputPass.setTexture('tDiffuse', this.dynamicAoPass.outputTexture) + this.copyOutputPass.setOutputType(PipelineOutputType.COLOR) + this.dynamicAoPass.setOutputType(DynamicAOOutputType.AO_BLURRED) break default: break @@ -155,6 +221,7 @@ export class Pipeline { this.composer.addPass(this.copyOutputPass) this.dynamicAoPass.setTexture('tDepth', this.depthPass.outputTexture) + this.dynamicAoPass.setTexture('tNormal', this.normalsPass.outputTexture) this.applySaoPass.setTexture('tDiffuse', this.dynamicAoPass.outputTexture) let restoreVisibility diff --git a/packages/viewer/src/modules/pipeline/SpecklePass.ts b/packages/viewer/src/modules/pipeline/SpecklePass.ts index 0451fcb50..bc71e494e 100644 --- a/packages/viewer/src/modules/pipeline/SpecklePass.ts +++ b/packages/viewer/src/modules/pipeline/SpecklePass.ts @@ -2,6 +2,7 @@ import { Camera, Plane, Scene, Texture } from 'three' export type InputColorTextureUniform = 'tDiffuse' export type InputDepthTextureUniform = 'tDepth' +export type InputNormalsTextureUniform = 'tNormal' export interface SpecklePass { onBeforeRender?: () => void