Restructuring how the pipeline and it's passes work so we can extend/configure them more easily. Added the concept of SpecklePass
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
import {
|
||||
Camera,
|
||||
Color,
|
||||
DoubleSide,
|
||||
NoBlending,
|
||||
RGBADepthPacking,
|
||||
Scene,
|
||||
Texture,
|
||||
WebGLRenderTarget
|
||||
} from 'three'
|
||||
import { Pass } from 'three/examples/jsm/postprocessing/Pass'
|
||||
import SpeckleDepthMaterial from '../materials/SpeckleDepthMaterial'
|
||||
import { SpecklePass } from './Pipeline'
|
||||
|
||||
export class DepthPass extends Pass implements SpecklePass {
|
||||
private renderTarget: WebGLRenderTarget
|
||||
private depthMaterial: SpeckleDepthMaterial = null
|
||||
private scene: Scene
|
||||
private camera: Camera
|
||||
|
||||
private colorBuffer: Color = new Color()
|
||||
|
||||
get displayName(): string {
|
||||
return 'DEPTH'
|
||||
}
|
||||
|
||||
get outputTexture(): Texture {
|
||||
return this.renderTarget.texture
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
|
||||
this.renderTarget = new WebGLRenderTarget(256, 256)
|
||||
/** On Chromium, on MacOS the 16 bit depth render buffer appears broken.
|
||||
* We're not really using a stencil buffer at all, we're just forcing
|
||||
* three.js to use a 24 bit depth render buffer
|
||||
*/
|
||||
this.renderTarget.depthBuffer = true
|
||||
this.renderTarget.stencilBuffer = true
|
||||
|
||||
this.depthMaterial = new SpeckleDepthMaterial(
|
||||
{
|
||||
depthPacking: RGBADepthPacking
|
||||
},
|
||||
['USE_RTE', 'ALPHATEST_REJECTION']
|
||||
)
|
||||
this.depthMaterial.blending = NoBlending
|
||||
this.depthMaterial.side = DoubleSide
|
||||
}
|
||||
|
||||
public update(camera: Camera, scene: Scene) {
|
||||
this.camera = camera
|
||||
this.scene = scene
|
||||
}
|
||||
|
||||
public render(renderer, writeBuffer, readBuffer) {
|
||||
writeBuffer
|
||||
readBuffer
|
||||
|
||||
renderer.getClearColor(this.colorBuffer)
|
||||
const originalClearAlpha = renderer.getClearAlpha()
|
||||
const originalAutoClear = renderer.autoClear
|
||||
|
||||
renderer.setRenderTarget(this.renderTarget)
|
||||
renderer.autoClear = false
|
||||
|
||||
renderer.setClearColor(0x000000)
|
||||
renderer.setClearAlpha(1.0)
|
||||
renderer.clear()
|
||||
|
||||
const shadowmapEnabled = renderer.shadowMap.enabled
|
||||
const shadowmapNeedsUpdate = renderer.shadowMap.needsUpdate
|
||||
this.scene.overrideMaterial = this.depthMaterial
|
||||
renderer.shadowMap.enabled = false
|
||||
renderer.shadowMap.needsUpdate = false
|
||||
renderer.render(this.scene, this.camera)
|
||||
renderer.shadowMap.enabled = shadowmapEnabled
|
||||
renderer.shadowMap.needsUpdate = shadowmapNeedsUpdate
|
||||
this.scene.overrideMaterial = null
|
||||
|
||||
// restore original state
|
||||
renderer.autoClear = originalAutoClear
|
||||
renderer.setClearColor(this.colorBuffer)
|
||||
renderer.setClearAlpha(originalClearAlpha)
|
||||
}
|
||||
|
||||
public setSize(width: number, height: number) {
|
||||
this.renderTarget.setSize(width, height)
|
||||
}
|
||||
}
|
||||
@@ -1,111 +1,61 @@
|
||||
import { Camera, Plane, Scene, Vector2, WebGLRenderer } from 'three'
|
||||
import { Camera, Plane, Scene, Texture, Vector2, WebGLRenderer } from 'three'
|
||||
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js'
|
||||
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js'
|
||||
import { SAOPassParams } from 'three/examples/jsm/postprocessing/SAOPass.js'
|
||||
import Batcher from '../batching/Batcher'
|
||||
import { ApplySAOPass } from './ApplySAOPass'
|
||||
import { NormalsType, SpeckleDynamicSAOPass } from './SpeckleDynamicSAOPass'
|
||||
import {
|
||||
DefaultSpeckleDynamicSAOPassParams,
|
||||
NormalsType,
|
||||
SpeckleDynamicSAOPass,
|
||||
SpeckleDynamicSAOPassParams
|
||||
} from './SpeckleDynamicSAOPass'
|
||||
import { SpeckleStaticAOGeneratePass } from './SpeckleStaticAOGeneratePass'
|
||||
|
||||
enum RenderType {
|
||||
NORMAL,
|
||||
ACCUMULATION
|
||||
}
|
||||
export interface SpecklePass {
|
||||
get displayName(): string
|
||||
get outputTexture(): Texture
|
||||
}
|
||||
|
||||
export interface PipelineOptions {
|
||||
saoEnabled?: boolean
|
||||
saoParams?: Partial<SAOPassParams>
|
||||
saoScaleOffset?: number
|
||||
saoNormalsRendering?: NormalsType
|
||||
minDistance?: number
|
||||
maxDistance?: number
|
||||
ssaoKernelRadius?: number
|
||||
progressiveAO?: number
|
||||
progressive?: boolean
|
||||
dynamicAoEnabled: boolean
|
||||
dynamicAoParams: SpeckleDynamicSAOPassParams
|
||||
}
|
||||
|
||||
export const DefaultPipelineOptions: PipelineOptions = {
|
||||
saoEnabled: true,
|
||||
saoParams: {
|
||||
saoBias: 0.15,
|
||||
saoIntensity: 1.25,
|
||||
saoScale: 434,
|
||||
saoKernelRadius: 10,
|
||||
saoMinResolution: 0,
|
||||
saoBlur: true,
|
||||
saoBlurRadius: 4,
|
||||
saoBlurStdDev: 4,
|
||||
saoBlurDepthCutoff: 0.0007
|
||||
},
|
||||
saoScaleOffset: 0,
|
||||
saoNormalsRendering: NormalsType.ACCURATE,
|
||||
minDistance: 0,
|
||||
maxDistance: 0.008,
|
||||
ssaoKernelRadius: 0.5,
|
||||
progressiveAO: 0,
|
||||
progressive: true
|
||||
dynamicAoEnabled: true,
|
||||
dynamicAoParams: DefaultSpeckleDynamicSAOPassParams
|
||||
// saoScaleOffset: 0,
|
||||
// saoNormalsRendering: NormalsType.ACCURATE,
|
||||
// minDistance: 0,
|
||||
// maxDistance: 0.008,
|
||||
// ssaoKernelRadius: 0.5,
|
||||
// progressiveAO: 0,
|
||||
// progressive: true
|
||||
}
|
||||
|
||||
export class Pipeline {
|
||||
private _renderer: WebGLRenderer = null
|
||||
private _batcher: Batcher = null
|
||||
private _pipelineOptions: PipelineOptions = {}
|
||||
private _pipelineOptions: PipelineOptions = Object.assign({}, DefaultPipelineOptions)
|
||||
private composer: EffectComposer = null
|
||||
|
||||
private renderPass: RenderPass = null
|
||||
private saoPass: SpeckleDynamicSAOPass = null
|
||||
private dynamicAoPass: SpeckleDynamicSAOPass = null
|
||||
private applySaoPass: ApplySAOPass = null
|
||||
private staticAOGenerationPass: SpeckleStaticAOGeneratePass = null
|
||||
|
||||
private drawingSize: Vector2 = new Vector2()
|
||||
private _renderType: RenderType = RenderType.NORMAL
|
||||
private accumulationFrame = 0
|
||||
private readonly NUM_ACCUMULATION_FRAMES = 16
|
||||
private enableProgressive = true
|
||||
|
||||
public set pipelineOptions(options: PipelineOptions) {
|
||||
public set pipelineOptions(options: Partial<PipelineOptions>) {
|
||||
Object.assign(this._pipelineOptions, options)
|
||||
if (this.saoPass) {
|
||||
this.applySaoPass.enabled = this._pipelineOptions.saoEnabled
|
||||
Object.assign(this.saoPass.params, this._pipelineOptions.saoParams)
|
||||
this.saoPass.params.saoScale += this._pipelineOptions.saoScaleOffset
|
||||
this.saoPass.normalsRendering = this._pipelineOptions.saoNormalsRendering
|
||||
if (
|
||||
this.staticAOGenerationPass.minDistance !== this._pipelineOptions.minDistance ||
|
||||
this.staticAOGenerationPass.maxDistance !== this._pipelineOptions.maxDistance
|
||||
)
|
||||
this.accumulationFrame = 0
|
||||
if (
|
||||
this._pipelineOptions.ssaoKernelRadius !== undefined &&
|
||||
this.staticAOGenerationPass.ssaoKernelRadius !==
|
||||
this._pipelineOptions.ssaoKernelRadius
|
||||
) {
|
||||
this.accumulationFrame = 0
|
||||
this.staticAOGenerationPass.ssaoKernelRadius =
|
||||
this._pipelineOptions.ssaoKernelRadius
|
||||
}
|
||||
if (
|
||||
this._pipelineOptions.progressiveAO !== undefined &&
|
||||
this.staticAOGenerationPass.progressiveAO !==
|
||||
this._pipelineOptions.progressiveAO
|
||||
) {
|
||||
this.accumulationFrame = 0
|
||||
this.staticAOGenerationPass.progressiveAO = this._pipelineOptions.progressiveAO
|
||||
this.staticAOGenerationPass.aoMaterial.defines['AO_ESTIMATOR'] =
|
||||
this._pipelineOptions.progressiveAO
|
||||
this.staticAOGenerationPass.aoMaterial.needsUpdate = true
|
||||
}
|
||||
this.staticAOGenerationPass.minDistance = this._pipelineOptions.minDistance
|
||||
this.staticAOGenerationPass.maxDistance = this._pipelineOptions.maxDistance
|
||||
if (
|
||||
this._pipelineOptions.saoParams.saoKernelRadius !== undefined &&
|
||||
this.staticAOGenerationPass.kernelRadius !==
|
||||
this._pipelineOptions.saoParams.saoKernelRadius
|
||||
) {
|
||||
this.accumulationFrame = 0
|
||||
this.staticAOGenerationPass.kernelRadius =
|
||||
this._pipelineOptions.saoParams.saoKernelRadius
|
||||
}
|
||||
this.enableProgressive = this._pipelineOptions.progressive
|
||||
}
|
||||
}
|
||||
|
||||
private set renderType(value: RenderType) {
|
||||
@@ -121,7 +71,7 @@ export class Pipeline {
|
||||
}
|
||||
|
||||
public configure(scene: Scene, camera: Camera) {
|
||||
this.saoPass = new SpeckleDynamicSAOPass(
|
||||
this.dynamicAoPass = new SpeckleDynamicSAOPass(
|
||||
scene,
|
||||
camera,
|
||||
this._batcher,
|
||||
@@ -129,22 +79,23 @@ export class Pipeline {
|
||||
NormalsType.IMPROVED
|
||||
)
|
||||
this.staticAOGenerationPass = new SpeckleStaticAOGeneratePass(this._batcher)
|
||||
this.staticAOGenerationPass.depthTexture = this.saoPass.depthRenderTarget.texture
|
||||
this.composer.addPass(this.saoPass)
|
||||
this.staticAOGenerationPass.depthTexture =
|
||||
this.dynamicAoPass.depthRenderTarget.texture
|
||||
this.composer.addPass(this.dynamicAoPass)
|
||||
this.renderPass = new RenderPass(scene, camera)
|
||||
this.renderPass.renderToScreen = true
|
||||
// this.renderPass.enabled = false
|
||||
this.composer.addPass(this.renderPass)
|
||||
this.composer.addPass(this.staticAOGenerationPass)
|
||||
this.applySaoPass = new ApplySAOPass()
|
||||
this.applySaoPass.setAoTexture(this.saoPass.saoRenderTarget.texture)
|
||||
this.applySaoPass.setAoTexture(this.dynamicAoPass.saoRenderTarget.texture)
|
||||
this.applySaoPass.renderToScreen = true
|
||||
this.composer.addPass(this.applySaoPass)
|
||||
}
|
||||
|
||||
public updateClippingPlanes(planes: Plane[]) {
|
||||
this.saoPass.depthMaterial.clippingPlanes = planes
|
||||
this.saoPass.normalMaterial.clippingPlanes = planes
|
||||
this.dynamicAoPass.depthMaterial.clippingPlanes = planes
|
||||
this.dynamicAoPass.normalMaterial.clippingPlanes = planes
|
||||
}
|
||||
|
||||
public render(scene: Scene, camera: Camera): boolean {
|
||||
@@ -153,11 +104,11 @@ export class Pipeline {
|
||||
|
||||
if (this._renderType === RenderType.NORMAL) {
|
||||
this._renderer.clear(true)
|
||||
this.applySaoPass.setAoTexture(this.saoPass.saoRenderTarget.texture)
|
||||
this.applySaoPass.setAoTexture(this.dynamicAoPass.saoRenderTarget.texture)
|
||||
this.renderPass.scene = scene
|
||||
this.renderPass.camera = camera
|
||||
this.saoPass.scene = scene
|
||||
this.saoPass.camera = camera
|
||||
this.dynamicAoPass.scene = scene
|
||||
this.dynamicAoPass.camera = camera
|
||||
this.composer.render()
|
||||
return true
|
||||
} else if (this.enableProgressive) {
|
||||
@@ -165,8 +116,8 @@ export class Pipeline {
|
||||
this.applySaoPass.setAoTexture(this.staticAOGenerationPass.outputTexture.texture)
|
||||
this.renderPass.scene = scene
|
||||
this.renderPass.camera = camera
|
||||
this.saoPass.scene = scene
|
||||
this.saoPass.camera = camera
|
||||
this.dynamicAoPass.scene = scene
|
||||
this.dynamicAoPass.camera = camera
|
||||
this.staticAOGenerationPass.update(camera, this.accumulationFrame)
|
||||
this.composer.render()
|
||||
this.accumulationFrame++
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
import {
|
||||
AdditiveBlending,
|
||||
Camera,
|
||||
DoubleSide,
|
||||
Color,
|
||||
NoBlending,
|
||||
OrthographicCamera,
|
||||
PerspectiveCamera,
|
||||
RGBADepthPacking,
|
||||
Scene,
|
||||
ShaderMaterial,
|
||||
Texture,
|
||||
UniformsUtils,
|
||||
Vector2
|
||||
Vector2,
|
||||
WebGLRenderTarget
|
||||
} from 'three'
|
||||
import { FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass'
|
||||
import { SAOPass } from 'three/examples/jsm/postprocessing/SAOPass.js'
|
||||
import { BlurShaderUtils } from 'three/examples/jsm/shaders/DepthLimitedBlurShader.js'
|
||||
import { FullScreenQuad, Pass } from 'three/examples/jsm/postprocessing/Pass'
|
||||
import { speckleSaoFrag } from '../materials/shaders/speckle-sao-frag'
|
||||
import { speckleSaoVert } from '../materials/shaders/speckle-sao-vert'
|
||||
import { SAOShader } from 'three/examples/jsm/shaders/SAOShader.js'
|
||||
import Batcher from '../batching/Batcher'
|
||||
import SpeckleDepthMaterial from '../materials/SpeckleDepthMaterial'
|
||||
import SpeckleNormalMaterial from '../materials/SpeckleNormalMaterial'
|
||||
import { DepthLimitedBlurShader } from 'three/examples/jsm/shaders/DepthLimitedBlurShader.js'
|
||||
import { BlurShaderUtils } from 'three/examples/jsm/shaders/DepthLimitedBlurShader.js'
|
||||
import { SpecklePass } from './Pipeline'
|
||||
|
||||
export enum NormalsType {
|
||||
DEFAULT = 0,
|
||||
@@ -27,62 +25,75 @@ export enum NormalsType {
|
||||
ACCURATE = 2
|
||||
}
|
||||
|
||||
export interface SpeckleDynamicSAOPassParams {
|
||||
intensity: number
|
||||
scale: number
|
||||
kernelRadius: number
|
||||
bias: number
|
||||
normalsType: NormalsType
|
||||
blurEnabled: boolean
|
||||
blurRadius: number
|
||||
blurStdDev: number
|
||||
blurDepthCutoff: number
|
||||
}
|
||||
|
||||
export const DefaultSpeckleDynamicSAOPassParams = {
|
||||
intensity: 1.25,
|
||||
scale: 0,
|
||||
kernelRadius: 10,
|
||||
bias: 0.15,
|
||||
normalsType: NormalsType.ACCURATE,
|
||||
blurEnabled: true,
|
||||
blurRadius: 4,
|
||||
blurStdDev: 4,
|
||||
blurDepthCutoff: 0.0007
|
||||
}
|
||||
|
||||
/**
|
||||
* SAO implementation inspired from bhouston previous SAO work
|
||||
*/
|
||||
|
||||
export class SpeckleDynamicSAOPass extends SAOPass {
|
||||
private _oldClearColor
|
||||
private prevStdDev
|
||||
private prevNumSamples
|
||||
private batcher: Batcher = null
|
||||
private normalsType: NormalsType = NormalsType.IMPROVED
|
||||
export class SpeckleDynamicSAOPass extends Pass implements SpecklePass {
|
||||
private params: SpeckleDynamicSAOPassParams
|
||||
private colorBuffer: Color = new Color()
|
||||
private saoMaterial: ShaderMaterial = null
|
||||
private vBlurMaterial: ShaderMaterial = null
|
||||
private hBlurMaterial: ShaderMaterial = null
|
||||
private saoRenderTarget: WebGLRenderTarget = null
|
||||
private blurIntermediateRenderTarget: WebGLRenderTarget = null
|
||||
private fsQuad: FullScreenQuad = null
|
||||
|
||||
public set normalsRendering(type: NormalsType) {
|
||||
this.normalsType = type
|
||||
this.saoMaterial.defines['NORMAL_TEXTURE'] =
|
||||
this.normalsType === NormalsType.DEFAULT ? 1 : 0
|
||||
this.saoMaterial.defines['IMPROVED_NORMAL_RECONSTRUCTION'] =
|
||||
this.normalsType === NormalsType.IMPROVED ? 1 : 0
|
||||
this.saoMaterial.defines['ACCURATE_NORMAL_RECONSTRUCTION'] =
|
||||
this.normalsType === NormalsType.ACCURATE ? 1 : 0
|
||||
this.saoMaterial.needsUpdate = true
|
||||
private prevStdDev: number
|
||||
private prevNumSamples: number
|
||||
|
||||
get displayName(): string {
|
||||
return 'SAO'
|
||||
}
|
||||
|
||||
constructor(
|
||||
scene: Scene,
|
||||
camera: Camera,
|
||||
batcher: Batcher,
|
||||
useDepthTexture = false,
|
||||
normalsType: NormalsType,
|
||||
resolution = new Vector2(256, 256)
|
||||
) {
|
||||
super(scene, camera, useDepthTexture, true, resolution)
|
||||
get outputTexture(): Texture {
|
||||
return this.saoRenderTarget.texture
|
||||
}
|
||||
|
||||
this.batcher = batcher
|
||||
public setDepthTexture(texture: Texture) {
|
||||
this.saoMaterial.uniforms['tDepth'].value = texture
|
||||
this.vBlurMaterial.uniforms['tDepth'].value = texture
|
||||
this.hBlurMaterial.uniforms['tDepth'].value = texture
|
||||
this.saoMaterial.needsUpdate = true
|
||||
this.vBlurMaterial.needsUpdate = true
|
||||
this.hBlurMaterial.needsUpdate = true
|
||||
}
|
||||
|
||||
/** On Chromium, on MacOS the 16 bit depth render buffer appears broken.
|
||||
* We're not really using a stencil buffer at all, we're just forcing
|
||||
* three.js to use a 24 bit depth render buffer
|
||||
*/
|
||||
this.depthRenderTarget.depthBuffer = true
|
||||
this.depthRenderTarget.stencilBuffer = true
|
||||
this.normalRenderTarget.depthBuffer = true
|
||||
this.normalRenderTarget.stencilBuffer = true
|
||||
constructor() {
|
||||
super()
|
||||
|
||||
this.depthMaterial = new SpeckleDepthMaterial(
|
||||
{
|
||||
depthPacking: RGBADepthPacking
|
||||
},
|
||||
['USE_RTE', 'ALPHATEST_REJECTION']
|
||||
)
|
||||
this.depthMaterial.blending = NoBlending
|
||||
this.depthMaterial.side = DoubleSide
|
||||
|
||||
this.normalMaterial = new SpeckleNormalMaterial({}, ['USE_RTE'])
|
||||
this.normalMaterial.blending = NoBlending
|
||||
this.normalMaterial.side = DoubleSide
|
||||
// this.normalRenderTarget.depthBuffer = true
|
||||
// this.normalRenderTarget.stencilBuffer = true
|
||||
|
||||
// this.normalMaterial = new SpeckleNormalMaterial({}, ['USE_RTE'])
|
||||
// this.normalMaterial.blending = NoBlending
|
||||
// this.normalMaterial.side = DoubleSide
|
||||
this.saoRenderTarget = new WebGLRenderTarget(256, 256)
|
||||
this.blurIntermediateRenderTarget = new WebGLRenderTarget(256, 256)
|
||||
this.saoMaterial = new ShaderMaterial({
|
||||
defines: {
|
||||
NUM_SAMPLES: 7,
|
||||
@@ -96,211 +107,184 @@ export class SpeckleDynamicSAOPass extends SAOPass {
|
||||
vertexShader: speckleSaoVert,
|
||||
uniforms: UniformsUtils.clone(SAOShader.uniforms)
|
||||
})
|
||||
this.normalsRendering = normalsType
|
||||
this.saoMaterial.extensions.derivatives = true
|
||||
this.saoMaterial.defines['DEPTH_PACKING'] = this.supportsDepthTextureExtension
|
||||
? 0
|
||||
: 1
|
||||
this.saoMaterial.defines['PERSPECTIVE_CAMERA'] = (this.camera as PerspectiveCamera)
|
||||
this.saoMaterial.defines['DEPTH_PACKING'] = 1
|
||||
this.saoMaterial.uniforms['tDepth'].value = null
|
||||
this.saoMaterial.uniforms['tNormal'].value = null
|
||||
this.saoMaterial.uniforms['size'].value.set(256, 256)
|
||||
this.saoMaterial.uniforms['minResolution'].value = 0
|
||||
this.saoMaterial.blending = NoBlending
|
||||
|
||||
this.vBlurMaterial = new ShaderMaterial({
|
||||
uniforms: UniformsUtils.clone(DepthLimitedBlurShader.uniforms),
|
||||
defines: Object.assign({}, DepthLimitedBlurShader.defines),
|
||||
vertexShader: DepthLimitedBlurShader.vertexShader,
|
||||
fragmentShader: DepthLimitedBlurShader.fragmentShader
|
||||
})
|
||||
this.vBlurMaterial.defines['DEPTH_PACKING'] = 1
|
||||
|
||||
this.vBlurMaterial.uniforms['tDiffuse'].value = this.saoRenderTarget.texture
|
||||
this.vBlurMaterial.uniforms['tDepth'].value = null
|
||||
this.vBlurMaterial.uniforms['size'].value.set(256, 256)
|
||||
this.vBlurMaterial.blending = NoBlending
|
||||
|
||||
this.hBlurMaterial = new ShaderMaterial({
|
||||
uniforms: UniformsUtils.clone(DepthLimitedBlurShader.uniforms),
|
||||
defines: Object.assign({}, DepthLimitedBlurShader.defines),
|
||||
vertexShader: DepthLimitedBlurShader.vertexShader,
|
||||
fragmentShader: DepthLimitedBlurShader.fragmentShader
|
||||
})
|
||||
this.hBlurMaterial.defines['DEPTH_PACKING'] = 1
|
||||
|
||||
this.hBlurMaterial.uniforms['tDiffuse'].value =
|
||||
this.blurIntermediateRenderTarget.texture
|
||||
this.hBlurMaterial.uniforms['tDepth'].value = null
|
||||
this.hBlurMaterial.uniforms['size'].value.set(256, 256)
|
||||
this.hBlurMaterial.blending = NoBlending
|
||||
|
||||
this.fsQuad = new FullScreenQuad(this.saoMaterial)
|
||||
}
|
||||
|
||||
public update(scene: Scene, camera: Camera) {
|
||||
/** SAO DEFINES */
|
||||
this.saoMaterial.defines['PERSPECTIVE_CAMERA'] = (camera as PerspectiveCamera)
|
||||
.isPerspectiveCamera
|
||||
? 1
|
||||
: 0
|
||||
this.saoMaterial.uniforms['tDepth'].value = this.supportsDepthTextureExtension
|
||||
? this.beautyRenderTarget.depthTexture
|
||||
: this.depthRenderTarget.texture
|
||||
this.saoMaterial.uniforms['tNormal'].value = this.normalRenderTarget.texture
|
||||
this.saoMaterial.uniforms['size'].value.set(this.resolution.x, this.resolution.y)
|
||||
|
||||
this.saoMaterial.defines['NORMAL_TEXTURE'] =
|
||||
this.params.normalsType === NormalsType.DEFAULT ? 1 : 0
|
||||
this.saoMaterial.defines['IMPROVED_NORMAL_RECONSTRUCTION'] =
|
||||
this.params.normalsType === NormalsType.IMPROVED ? 1 : 0
|
||||
this.saoMaterial.defines['ACCURATE_NORMAL_RECONSTRUCTION'] =
|
||||
this.params.normalsType === NormalsType.ACCURATE ? 1 : 0
|
||||
|
||||
/** SAO UNIFORMS */
|
||||
this.saoMaterial.uniforms['cameraNear'].value = (
|
||||
camera as PerspectiveCamera | OrthographicCamera
|
||||
).near
|
||||
this.saoMaterial.uniforms['cameraFar'].value = (
|
||||
camera as PerspectiveCamera | OrthographicCamera
|
||||
).far
|
||||
this.saoMaterial.uniforms['cameraInverseProjectionMatrix'].value.copy(
|
||||
this.camera.projectionMatrixInverse
|
||||
camera.projectionMatrixInverse
|
||||
)
|
||||
this.saoMaterial.uniforms['cameraProjectionMatrix'].value =
|
||||
this.camera.projectionMatrix
|
||||
this.saoMaterial.blending = NoBlending
|
||||
this.saoMaterial.uniforms['cameraProjectionMatrix'].value = camera.projectionMatrix
|
||||
|
||||
/** SAO UNIFORM PARAMS */
|
||||
this.saoMaterial.uniforms['intensity'].value = this.params.intensity
|
||||
this.saoMaterial.uniforms['scale'].value = this.params.scale
|
||||
this.saoMaterial.uniforms['kernelRadius'].value = this.params.kernelRadius
|
||||
this.saoMaterial.uniforms['bias'].value = this.params.bias
|
||||
|
||||
this.saoMaterial.needsUpdate = true
|
||||
|
||||
/** BLUR DEFINES */
|
||||
this.vBlurMaterial.defines['PERSPECTIVE_CAMERA'] = (camera as PerspectiveCamera)
|
||||
.isPerspectiveCamera
|
||||
? 1
|
||||
: 0
|
||||
this.hBlurMaterial.defines['PERSPECTIVE_CAMERA'] = (camera as PerspectiveCamera)
|
||||
.isPerspectiveCamera
|
||||
? 1
|
||||
: 0
|
||||
|
||||
/** BLUR UNIFORMS */
|
||||
this.vBlurMaterial.uniforms['cameraNear'].value = (
|
||||
camera as PerspectiveCamera | OrthographicCamera
|
||||
).near
|
||||
this.vBlurMaterial.uniforms['cameraFar'].value = (
|
||||
camera as PerspectiveCamera | OrthographicCamera
|
||||
).far
|
||||
this.hBlurMaterial.uniforms['cameraNear'].value = (
|
||||
camera as PerspectiveCamera | OrthographicCamera
|
||||
).near
|
||||
this.hBlurMaterial.uniforms['cameraFar'].value = (
|
||||
camera as PerspectiveCamera | OrthographicCamera
|
||||
).far
|
||||
|
||||
/** BLUR UNIFORM PARAMS */
|
||||
const depthCutoff =
|
||||
this.params.blurDepthCutoff *
|
||||
((camera as PerspectiveCamera | OrthographicCamera).far -
|
||||
(camera as PerspectiveCamera | OrthographicCamera).near)
|
||||
this.vBlurMaterial.uniforms['depthCutoff'].value = depthCutoff
|
||||
this.hBlurMaterial.uniforms['depthCutoff'].value = depthCutoff
|
||||
|
||||
this.params.blurRadius = Math.floor(this.params.blurRadius)
|
||||
if (
|
||||
this.prevStdDev !== this.params.blurStdDev ||
|
||||
this.prevNumSamples !== this.params.blurRadius
|
||||
) {
|
||||
BlurShaderUtils.configure(
|
||||
this.vBlurMaterial,
|
||||
this.params.blurRadius,
|
||||
this.params.blurStdDev,
|
||||
new Vector2(0, 1)
|
||||
)
|
||||
BlurShaderUtils.configure(
|
||||
this.hBlurMaterial,
|
||||
this.params.blurRadius,
|
||||
this.params.blurStdDev,
|
||||
new Vector2(1, 0)
|
||||
)
|
||||
this.prevStdDev = this.params.blurStdDev
|
||||
this.prevNumSamples = this.params.blurRadius
|
||||
}
|
||||
this.vBlurMaterial.needsUpdate = true
|
||||
this.hBlurMaterial.needsUpdate = true
|
||||
}
|
||||
|
||||
public render(renderer, writeBuffer, readBuffer) {
|
||||
writeBuffer
|
||||
readBuffer
|
||||
if (this.params.output === 1) {
|
||||
return
|
||||
}
|
||||
|
||||
renderer.getClearColor(this._oldClearColor)
|
||||
this.oldClearAlpha = renderer.getClearAlpha()
|
||||
renderer.autoClear = false
|
||||
|
||||
renderer.setRenderTarget(this.depthRenderTarget)
|
||||
renderer.clear()
|
||||
this.saoMaterial.blending = AdditiveBlending
|
||||
this.saoMaterial.uniforms['bias'].value = this.params.saoBias
|
||||
this.saoMaterial.uniforms['intensity'].value = this.params.saoIntensity
|
||||
this.saoMaterial.uniforms['scale'].value = this.params.saoScale
|
||||
this.saoMaterial.uniforms['kernelRadius'].value = this.params.saoKernelRadius
|
||||
this.saoMaterial.uniforms['minResolution'].value = this.params.saoMinResolution
|
||||
this.saoMaterial.uniforms['cameraNear'].value = (
|
||||
this.camera as PerspectiveCamera | OrthographicCamera
|
||||
).near
|
||||
this.saoMaterial.uniforms['cameraFar'].value = (
|
||||
this.camera as PerspectiveCamera | OrthographicCamera
|
||||
).far
|
||||
this.saoMaterial.uniforms['cameraInverseProjectionMatrix'].value.copy(
|
||||
this.camera.projectionMatrixInverse
|
||||
)
|
||||
this.saoMaterial.uniforms['cameraProjectionMatrix'].value =
|
||||
this.camera.projectionMatrix
|
||||
// this.saoMaterial.uniforms['randomSeed'].value = Math.random()
|
||||
|
||||
const depthCutoff =
|
||||
this.params.saoBlurDepthCutoff *
|
||||
((this.camera as PerspectiveCamera | OrthographicCamera).far -
|
||||
(this.camera as PerspectiveCamera | OrthographicCamera).near)
|
||||
this.vBlurMaterial.uniforms['depthCutoff'].value = depthCutoff
|
||||
this.hBlurMaterial.uniforms['depthCutoff'].value = depthCutoff
|
||||
|
||||
this.vBlurMaterial.uniforms['cameraNear'].value = (
|
||||
this.camera as PerspectiveCamera | OrthographicCamera
|
||||
).near
|
||||
this.vBlurMaterial.uniforms['cameraFar'].value = (
|
||||
this.camera as PerspectiveCamera | OrthographicCamera
|
||||
).far
|
||||
this.hBlurMaterial.uniforms['cameraNear'].value = (
|
||||
this.camera as PerspectiveCamera | OrthographicCamera
|
||||
).near
|
||||
this.hBlurMaterial.uniforms['cameraFar'].value = (
|
||||
this.camera as PerspectiveCamera | OrthographicCamera
|
||||
).far
|
||||
|
||||
this.params.saoBlurRadius = Math.floor(this.params.saoBlurRadius)
|
||||
if (
|
||||
this.prevStdDev !== this.params.saoBlurStdDev ||
|
||||
this.prevNumSamples !== this.params.saoBlurRadius
|
||||
) {
|
||||
BlurShaderUtils.configure(
|
||||
this.vBlurMaterial,
|
||||
this.params.saoBlurRadius,
|
||||
this.params.saoBlurStdDev,
|
||||
new Vector2(0, 1)
|
||||
)
|
||||
BlurShaderUtils.configure(
|
||||
this.hBlurMaterial,
|
||||
this.params.saoBlurRadius,
|
||||
this.params.saoBlurStdDev,
|
||||
new Vector2(1, 0)
|
||||
)
|
||||
this.prevStdDev = this.params.saoBlurStdDev
|
||||
this.prevNumSamples = this.params.saoBlurRadius
|
||||
}
|
||||
|
||||
const restoreVisibility = this.batcher.saveVisiblity()
|
||||
const opaque = this.batcher.getOpaque()
|
||||
this.batcher.applyVisibility(opaque)
|
||||
// Re-render scene if depth texture extension is not supported
|
||||
if (!this.supportsDepthTextureExtension) {
|
||||
// Clear rule : far clipping plane in both RGBA and Basic encoding
|
||||
this.renderOverride(
|
||||
renderer,
|
||||
this.depthMaterial,
|
||||
this.depthRenderTarget,
|
||||
0x000000,
|
||||
1.0
|
||||
)
|
||||
}
|
||||
|
||||
if (this.normalsType === NormalsType.DEFAULT) {
|
||||
if (this.supportsNormalTexture) {
|
||||
// Clear rule : default normal is facing the camera
|
||||
this.renderOverride(
|
||||
renderer,
|
||||
this.normalMaterial,
|
||||
this.normalRenderTarget,
|
||||
0x7777ff,
|
||||
1.0
|
||||
)
|
||||
}
|
||||
}
|
||||
this.batcher.applyVisibility(restoreVisibility)
|
||||
// const restoreVisibility = this.batcher.saveVisiblity()
|
||||
// const opaque = this.batcher.getOpaque()
|
||||
// this.batcher.applyVisibility(opaque)
|
||||
// this.batcher.applyVisibility(restoreVisibility)
|
||||
|
||||
// Rendering SAO texture
|
||||
this.renderPass(renderer, this.saoMaterial, this.saoRenderTarget, 0x000000, 1.0)
|
||||
|
||||
// Blurring SAO texture
|
||||
if (this.params.saoBlur) {
|
||||
this.renderPass(
|
||||
renderer,
|
||||
this.vBlurMaterial,
|
||||
this.blurIntermediateRenderTarget,
|
||||
0xffffff,
|
||||
1.0
|
||||
)
|
||||
this.renderPass(renderer, this.hBlurMaterial, this.saoRenderTarget, 0xffffff, 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
public renderPass(
|
||||
renderer,
|
||||
passMaterial,
|
||||
renderTarget,
|
||||
clearColor = undefined,
|
||||
clearAlpha = undefined
|
||||
) {
|
||||
// save original state
|
||||
renderer.getClearColor(this.originalClearColor)
|
||||
renderer.getClearColor(this.colorBuffer)
|
||||
const originalClearAlpha = renderer.getClearAlpha()
|
||||
const originalAutoClear = renderer.autoClear
|
||||
|
||||
renderer.setRenderTarget(renderTarget)
|
||||
renderer.setRenderTarget(this.saoRenderTarget)
|
||||
|
||||
// setup pass state
|
||||
renderer.autoClear = false
|
||||
if (clearColor !== undefined && clearColor !== null) {
|
||||
renderer.setClearColor(clearColor)
|
||||
renderer.setClearAlpha(clearAlpha || 0.0)
|
||||
renderer.setClearColor(0xffffff)
|
||||
renderer.setClearAlpha(1.0)
|
||||
renderer.clear()
|
||||
this.fsQuad.material = this.saoMaterial
|
||||
this.fsQuad.render(renderer)
|
||||
|
||||
if (this.params.blurEnabled) {
|
||||
renderer.setRenderTarget(this.blurIntermediateRenderTarget)
|
||||
renderer.setClearColor(0xffffff)
|
||||
renderer.setClearAlpha(1.0)
|
||||
renderer.clear()
|
||||
this.fsQuad.material = this.vBlurMaterial
|
||||
this.fsQuad.render(renderer)
|
||||
|
||||
renderer.setRenderTarget(this.saoRenderTarget)
|
||||
this.fsQuad.material = this.hBlurMaterial
|
||||
this.fsQuad.render(renderer)
|
||||
}
|
||||
;(this.fsQuad as FullScreenQuad).material = passMaterial
|
||||
;(this.fsQuad as FullScreenQuad).render(renderer)
|
||||
|
||||
// restore original state
|
||||
renderer.autoClear = originalAutoClear
|
||||
renderer.setClearColor(this.originalClearColor)
|
||||
renderer.setClearColor(this.colorBuffer)
|
||||
renderer.setClearAlpha(originalClearAlpha)
|
||||
}
|
||||
|
||||
public renderOverride(
|
||||
renderer,
|
||||
overrideMaterial,
|
||||
renderTarget,
|
||||
clearColor,
|
||||
clearAlpha
|
||||
) {
|
||||
renderer.getClearColor(this.originalClearColor)
|
||||
const originalClearAlpha = renderer.getClearAlpha()
|
||||
const originalAutoClear = renderer.autoClear
|
||||
public setSize(width: number, height: number) {
|
||||
this.saoRenderTarget.setSize(width, height)
|
||||
this.blurIntermediateRenderTarget.setSize(width, height)
|
||||
|
||||
renderer.setRenderTarget(renderTarget)
|
||||
renderer.autoClear = false
|
||||
|
||||
clearColor = overrideMaterial.clearColor || clearColor
|
||||
clearAlpha = overrideMaterial.clearAlpha || clearAlpha
|
||||
if (clearColor !== undefined && clearColor !== null) {
|
||||
renderer.setClearColor(clearColor)
|
||||
renderer.setClearAlpha(clearAlpha || 0.0)
|
||||
renderer.clear()
|
||||
}
|
||||
|
||||
const shadowmapEnabled = renderer.shadowMap.enabled
|
||||
const shadowmapNeedsUpdate = renderer.shadowMap.needsUpdate
|
||||
this.scene.overrideMaterial = overrideMaterial
|
||||
renderer.shadowMap.enabled = false
|
||||
renderer.shadowMap.needsUpdate = false
|
||||
renderer.render(this.scene, this.camera)
|
||||
renderer.shadowMap.enabled = shadowmapEnabled
|
||||
renderer.shadowMap.needsUpdate = shadowmapNeedsUpdate
|
||||
this.scene.overrideMaterial = null
|
||||
|
||||
// restore original state
|
||||
renderer.autoClear = originalAutoClear
|
||||
renderer.setClearColor(this.originalClearColor)
|
||||
renderer.setClearAlpha(originalClearAlpha)
|
||||
this.saoMaterial.uniforms['size'].value.set(width, height)
|
||||
this.vBlurMaterial.uniforms['size'].value.set(width, height)
|
||||
this.hBlurMaterial.uniforms['size'].value.set(width, height)
|
||||
this.saoMaterial.needsUpdate = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +174,6 @@ export class SpeckleStaticAOGeneratePass extends Pass {
|
||||
public render(renderer, writeBuffer, readBuffer) {
|
||||
writeBuffer
|
||||
readBuffer
|
||||
|
||||
// save original state
|
||||
const originalClearColor = new Color()
|
||||
renderer.getClearColor(originalClearColor)
|
||||
|
||||
Reference in New Issue
Block a user