Skip to content

Commit

Permalink
SAOPass: Improve performance, fix visuals. (#26599)
Browse files Browse the repository at this point in the history
* SAOPass: Improve performance, fix visuals.

* Examples: Update screenshot.
  • Loading branch information
Mugen87 committed Aug 18, 2023
1 parent f7341c3 commit b37b76b
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 121 deletions.
121 changes: 23 additions & 98 deletions examples/jsm/postprocessing/SAOPass.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ import {
DstAlphaFactor,
DstColorFactor,
HalfFloatType,
MeshDepthMaterial,
MeshNormalMaterial,
NearestFilter,
NoBlending,
RGBADepthPacking,
ShaderMaterial,
UniformsUtils,
UnsignedShortType,
DepthStencilFormat,
UnsignedInt248Type,
Vector2,
WebGLRenderTarget,
ZeroFactor
Expand All @@ -23,15 +22,14 @@ import { SAOShader } from '../shaders/SAOShader.js';
import { DepthLimitedBlurShader } from '../shaders/DepthLimitedBlurShader.js';
import { BlurShaderUtils } from '../shaders/DepthLimitedBlurShader.js';
import { CopyShader } from '../shaders/CopyShader.js';
import { UnpackDepthRGBAShader } from '../shaders/UnpackDepthRGBAShader.js';

/**
* SAO implementation inspired from bhouston previous SAO work
*/

class SAOPass extends Pass {

constructor( scene, camera, useDepthTexture = false, useNormals = false, resolution = new Vector2( 256, 256 ) ) {
constructor( scene, camera, resolution = new Vector2( 256, 256 ) ) {

super();

Expand All @@ -41,9 +39,6 @@ class SAOPass extends Pass {
this.clear = true;
this.needsSwap = false;

this.supportsDepthTextureExtension = useDepthTexture;
this.supportsNormalTexture = useNormals;

this.originalClearColor = new Color();
this._oldClearColor = new Color();
this.oldClearAlpha = 1;
Expand All @@ -65,30 +60,17 @@ class SAOPass extends Pass {

this.saoRenderTarget = new WebGLRenderTarget( this.resolution.x, this.resolution.y, { type: HalfFloatType } );
this.blurIntermediateRenderTarget = this.saoRenderTarget.clone();
this.beautyRenderTarget = this.saoRenderTarget.clone();

const depthTexture = new DepthTexture();
depthTexture.format = DepthStencilFormat;
depthTexture.type = UnsignedInt248Type;

this.normalRenderTarget = new WebGLRenderTarget( this.resolution.x, this.resolution.y, {
minFilter: NearestFilter,
magFilter: NearestFilter,
type: HalfFloatType
type: HalfFloatType,
depthTexture: depthTexture
} );
this.depthRenderTarget = this.normalRenderTarget.clone();

let depthTexture;

if ( this.supportsDepthTextureExtension ) {

depthTexture = new DepthTexture();
depthTexture.type = UnsignedShortType;

this.beautyRenderTarget.depthTexture = depthTexture;
this.beautyRenderTarget.depthBuffer = true;

}

this.depthMaterial = new MeshDepthMaterial();
this.depthMaterial.depthPacking = RGBADepthPacking;
this.depthMaterial.blending = NoBlending;

this.normalMaterial = new MeshNormalMaterial();
this.normalMaterial.blending = NoBlending;
Expand All @@ -100,10 +82,8 @@ class SAOPass extends Pass {
uniforms: UniformsUtils.clone( SAOShader.uniforms )
} );
this.saoMaterial.extensions.derivatives = true;
this.saoMaterial.defines[ 'DEPTH_PACKING' ] = this.supportsDepthTextureExtension ? 0 : 1;
this.saoMaterial.defines[ 'NORMAL_TEXTURE' ] = this.supportsNormalTexture ? 1 : 0;
this.saoMaterial.defines[ 'PERSPECTIVE_CAMERA' ] = this.camera.isPerspectiveCamera ? 1 : 0;
this.saoMaterial.uniforms[ 'tDepth' ].value = ( this.supportsDepthTextureExtension ) ? depthTexture : this.depthRenderTarget.texture;
this.saoMaterial.uniforms[ 'tDepth' ].value = depthTexture;
this.saoMaterial.uniforms[ 'tNormal' ].value = this.normalRenderTarget.texture;
this.saoMaterial.uniforms[ 'size' ].value.set( this.resolution.x, this.resolution.y );
this.saoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
Expand All @@ -116,10 +96,10 @@ class SAOPass extends Pass {
vertexShader: DepthLimitedBlurShader.vertexShader,
fragmentShader: DepthLimitedBlurShader.fragmentShader
} );
this.vBlurMaterial.defines[ 'DEPTH_PACKING' ] = this.supportsDepthTextureExtension ? 0 : 1;
this.vBlurMaterial.defines[ 'DEPTH_PACKING' ] = 0;
this.vBlurMaterial.defines[ 'PERSPECTIVE_CAMERA' ] = this.camera.isPerspectiveCamera ? 1 : 0;
this.vBlurMaterial.uniforms[ 'tDiffuse' ].value = this.saoRenderTarget.texture;
this.vBlurMaterial.uniforms[ 'tDepth' ].value = ( this.supportsDepthTextureExtension ) ? depthTexture : this.depthRenderTarget.texture;
this.vBlurMaterial.uniforms[ 'tDepth' ].value = depthTexture;
this.vBlurMaterial.uniforms[ 'size' ].value.set( this.resolution.x, this.resolution.y );
this.vBlurMaterial.blending = NoBlending;

Expand All @@ -129,10 +109,10 @@ class SAOPass extends Pass {
vertexShader: DepthLimitedBlurShader.vertexShader,
fragmentShader: DepthLimitedBlurShader.fragmentShader
} );
this.hBlurMaterial.defines[ 'DEPTH_PACKING' ] = this.supportsDepthTextureExtension ? 0 : 1;
this.hBlurMaterial.defines[ 'DEPTH_PACKING' ] = 0;
this.hBlurMaterial.defines[ 'PERSPECTIVE_CAMERA' ] = this.camera.isPerspectiveCamera ? 1 : 0;
this.hBlurMaterial.uniforms[ 'tDiffuse' ].value = this.blurIntermediateRenderTarget.texture;
this.hBlurMaterial.uniforms[ 'tDepth' ].value = ( this.supportsDepthTextureExtension ) ? depthTexture : this.depthRenderTarget.texture;
this.hBlurMaterial.uniforms[ 'tDepth' ].value = depthTexture;
this.hBlurMaterial.uniforms[ 'size' ].value.set( this.resolution.x, this.resolution.y );
this.hBlurMaterial.blending = NoBlending;

Expand All @@ -153,13 +133,6 @@ class SAOPass extends Pass {
this.materialCopy.blendDstAlpha = ZeroFactor;
this.materialCopy.blendEquationAlpha = AddEquation;

this.depthCopy = new ShaderMaterial( {
uniforms: UniformsUtils.clone( UnpackDepthRGBAShader.uniforms ),
vertexShader: UnpackDepthRGBAShader.vertexShader,
fragmentShader: UnpackDepthRGBAShader.fragmentShader,
blending: NoBlending
} );

this.fsQuad = new FullScreenQuad( null );

}
Expand All @@ -176,20 +149,11 @@ class SAOPass extends Pass {

}

if ( this.params.output === 1 ) {

return;

}

renderer.getClearColor( this._oldClearColor );
this.oldClearAlpha = renderer.getClearAlpha();
const oldAutoClear = renderer.autoClear;
renderer.autoClear = false;

renderer.setRenderTarget( this.depthRenderTarget );
renderer.clear();

this.saoMaterial.uniforms[ 'bias' ].value = this.params.saoBias;
this.saoMaterial.uniforms[ 'intensity' ].value = this.params.saoIntensity;
this.saoMaterial.uniforms[ 'scale' ].value = this.params.saoScale;
Expand Down Expand Up @@ -218,26 +182,8 @@ class SAOPass extends Pass {

}

// Rendering scene to depth texture
renderer.setClearColor( 0x000000 );
renderer.setRenderTarget( this.beautyRenderTarget );
renderer.clear();
renderer.render( this.scene, this.camera );

// 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.supportsNormalTexture ) {

// Clear rule : default normal is facing the camera
this.renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0x7777ff, 1.0 );

}
// render normal and depth
this.renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0x7777ff, 1.0 );

// Rendering SAO texture
this.renderPass( renderer, this.saoMaterial, this.saoRenderTarget, 0xffffff, 1.0 );
Expand All @@ -250,24 +196,10 @@ class SAOPass extends Pass {

}

let outputMaterial = this.materialCopy;
// Setting up SAO rendering
if ( this.params.output === 3 ) {

if ( this.supportsDepthTextureExtension ) {

this.materialCopy.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.depthTexture;
this.materialCopy.needsUpdate = true;
const outputMaterial = this.materialCopy;

} else {

this.depthCopy.uniforms[ 'tDiffuse' ].value = this.depthRenderTarget.texture;
this.depthCopy.needsUpdate = true;
outputMaterial = this.depthCopy;

}

} else if ( this.params.output === 4 ) {
// Setting up SAO rendering
if ( this.params.output === SAOPass.OUTPUT.Normal ) {

this.materialCopy.uniforms[ 'tDiffuse' ].value = this.normalRenderTarget.texture;
this.materialCopy.needsUpdate = true;
Expand All @@ -279,8 +211,8 @@ class SAOPass extends Pass {

}

// Blending depends on output, only want a CustomBlending when showing SAO
if ( this.params.output === 0 ) {
// Blending depends on output
if ( this.params.output === SAOPass.OUTPUT.Default ) {

outputMaterial.blending = CustomBlending;

Expand Down Expand Up @@ -359,11 +291,9 @@ class SAOPass extends Pass {

setSize( width, height ) {

this.beautyRenderTarget.setSize( width, height );
this.saoRenderTarget.setSize( width, height );
this.blurIntermediateRenderTarget.setSize( width, height );
this.normalRenderTarget.setSize( width, height );
this.depthRenderTarget.setSize( width, height );

this.saoMaterial.uniforms[ 'size' ].value.set( width, height );
this.saoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
Expand All @@ -382,17 +312,14 @@ class SAOPass extends Pass {

this.saoRenderTarget.dispose();
this.blurIntermediateRenderTarget.dispose();
this.beautyRenderTarget.dispose();
this.normalRenderTarget.dispose();
this.depthRenderTarget.dispose();

this.depthMaterial.dispose();
this.normalMaterial.dispose();
this.saoMaterial.dispose();
this.vBlurMaterial.dispose();
this.hBlurMaterial.dispose();
this.materialCopy.dispose();
this.depthCopy.dispose();

this.fsQuad.dispose();

Expand All @@ -401,11 +328,9 @@ class SAOPass extends Pass {
}

SAOPass.OUTPUT = {
'Beauty': 1,
'Default': 0,
'SAO': 2,
'Depth': 3,
'Normal': 4
'SAO': 1,
'Normal': 2
};

export { SAOPass };
13 changes: 0 additions & 13 deletions examples/jsm/shaders/SAOShader.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ const SAOShader = {
defines: {
'NUM_SAMPLES': 7,
'NUM_RINGS': 4,
'NORMAL_TEXTURE': 0,
'DIFFUSE_TEXTURE': 0,
'DEPTH_PACKING': 1,
'PERSPECTIVE_CAMERA': 1
},
uniforms: {
Expand Down Expand Up @@ -56,10 +54,7 @@ const SAOShader = {
#endif
uniform sampler2D tDepth;
#if NORMAL_TEXTURE == 1
uniform sampler2D tNormal;
#endif
uniform float cameraNear;
uniform float cameraFar;
Expand Down Expand Up @@ -87,11 +82,7 @@ const SAOShader = {
}
float getDepth( const in vec2 screenPosition ) {
#if DEPTH_PACKING == 1
return unpackRGBAToDepth( texture2D( tDepth, screenPosition ) );
#else
return texture2D( tDepth, screenPosition ).x;
#endif
}
float getViewZ( const in float depth ) {
Expand All @@ -111,11 +102,7 @@ const SAOShader = {
}
vec3 getViewNormal( const in vec3 viewPosition, const in vec2 screenPosition ) {
#if NORMAL_TEXTURE == 1
return unpackRGBToNormal( texture2D( tNormal, screenPosition ).xyz );
#else
return normalize( cross( dFdx( viewPosition ), dFdy( viewPosition ) ) );
#endif
}
float scaleDividedByCameraFar;
Expand Down
Binary file modified examples/screenshots/webgl_postprocessing_sao.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 7 additions & 10 deletions examples/webgl_postprocessing_sao.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,11 @@
container = document.createElement( 'div' );
document.body.appendChild( container );

const width = window.innerWidth || 1;
const height = window.innerHeight || 1;
const devicePixelRatio = window.devicePixelRatio || 1;
const width = window.innerWidth;
const height = window.innerHeight;

renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setClearColor( 0x000000 );
renderer.setPixelRatio( devicePixelRatio );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( width, height );
document.body.appendChild( renderer.domElement );

Expand Down Expand Up @@ -117,18 +115,16 @@
composer = new EffectComposer( renderer );
renderPass = new RenderPass( scene, camera );
composer.addPass( renderPass );
saoPass = new SAOPass( scene, camera, false, true );
saoPass = new SAOPass( scene, camera );
composer.addPass( saoPass );
const outputPass = new OutputPass();
composer.addPass( outputPass );

// Init gui
const gui = new GUI();
gui.add( saoPass.params, 'output', {
'Beauty': SAOPass.OUTPUT.Beauty,
'Beauty+SAO': SAOPass.OUTPUT.Default,
'SAO': SAOPass.OUTPUT.SAO,
'Depth': SAOPass.OUTPUT.Depth,
'Default': SAOPass.OUTPUT.Default,
'SAO Only': SAOPass.OUTPUT.SAO,
'Normal': SAOPass.OUTPUT.Normal
} ).onChange( function ( value ) {

Expand All @@ -144,6 +140,7 @@
gui.add( saoPass.params, 'saoBlurRadius', 0, 200 );
gui.add( saoPass.params, 'saoBlurStdDev', 0.5, 150 );
gui.add( saoPass.params, 'saoBlurDepthCutoff', 0.0, 0.1 );
gui.add( saoPass, 'enabled' );

window.addEventListener( 'resize', onWindowResize );

Expand Down

0 comments on commit b37b76b

Please sign in to comment.