Intruduced accumulation frames properly at pipeline level. Cleaned up progressive AO shader and pass. Exposed the number of accumulation frames as well as the kernel size in the sandbox.
This commit is contained in:
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}`
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<PipelineOptions>) {
|
||||
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')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,3 +16,7 @@ export interface SpecklePass {
|
||||
setParams?(params: unknown)
|
||||
setClippingPlanes?(planes: Plane[])
|
||||
}
|
||||
|
||||
export interface SpeckleProgressivePass extends SpecklePass {
|
||||
setFrameIndex(index: number)
|
||||
}
|
||||
|
||||
+82
-55
@@ -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<Array<Vector3>> = new Array(16)
|
||||
private kernelSize = 16
|
||||
private kernels: Array<Array<Vector3>> = []
|
||||
private noiseTextures: Array<Texture> = []
|
||||
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++) {
|
||||
Reference in New Issue
Block a user