Skip to content

Commit

Permalink
feat: precalculate normal from depth
Browse files Browse the repository at this point in the history
  • Loading branch information
Rabbid76 committed Dec 14, 2023
1 parent 4bb9524 commit b715fd6
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 24 deletions.

Large diffs are not rendered by default.

File renamed without changes.
2 changes: 1 addition & 1 deletion dist/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>three.js Hello Cube</title><link rel="icon" type="image/x-icon" href="e5cc0d3a32b796a8.ico?v=2"><style>body,html{overflow:hidden;width:100%;height:100%;margin:0;padding:0}</style><script defer="defer" src="bundle.23f30fb963bfb9ac.js"></script></head><body><div id="container"><canvas id="three_canvas"></canvas></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>three.js Hello Cube</title><link rel="icon" type="image/x-icon" href="e5cc0d3a32b796a8.ico?v=2"><style>body,html{overflow:hidden;width:100%;height:100%;margin:0;padding:0}</style><script defer="defer" src="bundle.1d33abc0e2e0f1c6.js"></script></head><body><div id="container"><canvas id="three_canvas"></canvas></div></body></html>
54 changes: 40 additions & 14 deletions src/AOPass.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { Pass, FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass.js'
import { generatePdSamplePointInitializer, PoissonDenoiseShader } from 'three/examples/jsm/shaders/PoissonDenoiseShader.js';
import { CopyShader } from 'three/examples/jsm/shaders/CopyShader.js';
import { SimplexNoise } from 'three/examples/jsm/math/SimplexNoise.js';
import { generateAoSampleKernelInitializer, generateMagicSquareNoise, AOShader, AODepthShader, AoBlendShader } from './AOShader.js';
import { generateAoSampleKernelInitializer, generateMagicSquareNoise, AOShader, AoBlendShader, AODepthToNormalShader, AODepthShader } from './AOShader.js';

class AOPass extends Pass {

Expand All @@ -37,6 +37,7 @@ class AOPass extends Pass {
this.scene = scene;
this.output = 0;
this._renderGBuffer = true;
this._renderNormalFromDepth = false;
this._visibilityCache = new Map();
this.intensity = 1.;

Expand All @@ -63,12 +64,18 @@ class AOPass extends Pass {
this.aoMaterial.definesPERSPECTIVE_CAMERA = this.camera.isPerspectiveCamera ? 1 : 0;
this.aoMaterial.uniforms.tNoise.value = this.aoNoiseTextureMagicSquare;
this.aoMaterial.uniforms.resolution.value.set( this.width, this.height );
this.aoMaterial.uniforms.cameraNear.value = this.camera.near;
this.aoMaterial.uniforms.cameraFar.value = this.camera.far;

this.normalMaterial = new MeshNormalMaterial();
this.normalMaterial.blending = NoBlending;

this.depthToNormalRenderMaterial = new ShaderMaterial( {
defines: Object.assign( {}, AODepthToNormalShader.defines ),
uniforms: UniformsUtils.clone( AODepthToNormalShader.uniforms ),
vertexShader: AODepthToNormalShader.vertexShader,
fragmentShader: AODepthToNormalShader.fragmentShader,
blending: NoBlending
} );

this.pdMaterial = new ShaderMaterial( {
defines: Object.assign( {}, PoissonDenoiseShader.defines ),
uniforms: UniformsUtils.clone( PoissonDenoiseShader.uniforms ),
Expand All @@ -85,16 +92,6 @@ class AOPass extends Pass {
this.pdMaterial.uniforms.normalPhi.value = 3;
this.pdMaterial.uniforms.radius.value = 4;

this.depthRenderMaterial = new ShaderMaterial( {
defines: Object.assign( {}, AODepthShader.defines ),
uniforms: UniformsUtils.clone( AODepthShader.uniforms ),
vertexShader: AODepthShader.vertexShader,
fragmentShader: AODepthShader.fragmentShader,
blending: NoBlending
} );
this.depthRenderMaterial.uniforms.cameraNear.value = this.camera.near;
this.depthRenderMaterial.uniforms.cameraFar.value = this.camera.far;

this.copyMaterial = new ShaderMaterial( {
uniforms: UniformsUtils.clone( CopyShader.uniforms ),
vertexShader: CopyShader.vertexShader,
Expand Down Expand Up @@ -126,6 +123,16 @@ class AOPass extends Pass {
blendEquationAlpha: AddEquation
} );

this.depthRenderMaterial = new ShaderMaterial( {
defines: Object.assign( {}, AODepthShader.defines ),
uniforms: UniformsUtils.clone( AODepthShader.uniforms ),
vertexShader: AODepthShader.vertexShader,
fragmentShader: AODepthShader.fragmentShader,
blending: NoBlending
} );
this.depthRenderMaterial.uniforms.cameraNear.value = this.camera.near;
this.depthRenderMaterial.uniforms.cameraFar.value = this.camera.far;

this.fsQuad = new FullScreenQuad( null );

this.originalClearColor = new Color();
Expand Down Expand Up @@ -164,7 +171,19 @@ class AOPass extends Pass {

setGBuffer( depthTexture, normalTexture ) {

if ( depthTexture !== undefined ) {
if ( depthTexture !== undefined && normalTexture === undefined ) {

this.depthTexture = depthTexture;
this.normalRenderTarget = new WebGLRenderTarget( this.width, this.height, {
minFilter: NearestFilter,
magFilter: NearestFilter,
type: HalfFloatType
} );
this.normalTexture = this.normalRenderTarget.texture;
this._renderGBuffer = false;
this._renderNormalFromDepth = true;

} else if ( depthTexture !== undefined ) {

this.depthTexture = depthTexture;
this.normalTexture = normalTexture;
Expand Down Expand Up @@ -378,6 +397,12 @@ class AOPass extends Pass {
this.renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0x7777ff, 1.0 );
this.restoreVisibility();

} else if ( this._renderNormalFromDepth ) {

this.depthToNormalRenderMaterial.uniforms.tDepth.value = this.depthTexture;
this.depthToNormalRenderMaterial.uniforms.cameraProjectionMatrixInverse.value.copy( this.camera.projectionMatrixInverse );
this.renderPass( renderer, this.depthToNormalRenderMaterial, this.normalRenderTarget, 0x000000, 1.0 );

}

// render AO
Expand Down Expand Up @@ -424,6 +449,7 @@ class AOPass extends Pass {

case AOPass.OUTPUT.Depth:

this.depthRenderMaterial.uniforms.tDepth.value = this.depthTexture;
this.depthRenderMaterial.uniforms.cameraNear.value = this.camera.near;
this.depthRenderMaterial.uniforms.cameraFar.value = this.camera.far;
this.renderPass( renderer, this.depthRenderMaterial, this.renderToScreen ? null : writeBuffer );
Expand Down
94 changes: 91 additions & 3 deletions src/AOShader.js
Original file line number Diff line number Diff line change
Expand Up @@ -412,10 +412,98 @@ const AODepthShader = {
#endif
}
vec3 HUEtoRGB(in float H) {
float R = abs(H * 6.0 - 3.0) - 1.0;
float G = 2.0 - abs(H * 6.0 - 2.0);
float B = 2.0 - abs(H * 6.0 - 4.0);
return clamp( vec3(R,G,B), 0.0, 1.0 );
}
void main() {
float depth = getLinearDepth(vUv);
//gl_FragColor = vec4(HUEtoRGB(1.0 - depth), 1.0);
gl_FragColor = vec4(vec3(1.0 - depth) * HUEtoRGB(1.0 - depth), 1.0);
}`

};

const AODepthToNormalShader = {

name: 'HBAODepthShader',

defines: {
PERSPECTIVE_CAMERA: 1,
DEPTH_SWIZZLING: 'x'
},

uniforms: {
tDepth: { value: null },
cameraProjectionMatrixInverse: { value: new Matrix4() },
},

vertexShader: /* glsl */`
varying vec2 vUv;
void main() {
float depth = getLinearDepth( vUv );
gl_FragColor = vec4( vec3( 1.0 - depth ), 1.0 );
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`,

fragmentShader: /* glsl */`
varying vec2 vUv;
uniform sampler2D tDepth;
uniform mat4 cameraProjectionMatrixInverse;
#ifndef DEPTH_SWIZZLING
#define DEPTH_SWIZZLING x
#endif
#ifndef FRAGMENT_OUTPUT
#define FRAGMENT_OUTPUT vec4(vec3(normal) * 0.5 + 0.5, depth)
#endif
vec3 getViewPosition(const in vec2 screenPosition, const in float depth) {
vec4 clipSpacePosition = vec4(vec3(screenPosition, depth) * 2.0 - 1.0, 1.0);
vec4 viewSpacePosition = cameraProjectionMatrixInverse * clipSpacePosition;
return viewSpacePosition.xyz / viewSpacePosition.w;
}
float getDepth(const vec2 uv) {
return textureLod(tDepth, uv.xy, 0.0).DEPTH_SWIZZLING;
}
float fetchDepth(const ivec2 uv) {
return texelFetch(tDepth, uv.xy, 0).DEPTH_SWIZZLING;
}
vec3 computeNormalFromDepth(const vec2 uv) {
vec2 size = vec2(textureSize(tDepth, 0));
ivec2 p = ivec2(uv * size);
float c0 = fetchDepth(p);
float l2 = fetchDepth(p - ivec2(2, 0));
float l1 = fetchDepth(p - ivec2(1, 0));
float r1 = fetchDepth(p + ivec2(1, 0));
float r2 = fetchDepth(p + ivec2(2, 0));
float b2 = fetchDepth(p - ivec2(0, 2));
float b1 = fetchDepth(p - ivec2(0, 1));
float t1 = fetchDepth(p + ivec2(0, 1));
float t2 = fetchDepth(p + ivec2(0, 2));
float dl = abs((2.0 * l1 - l2) - c0);
float dr = abs((2.0 * r1 - r2) - c0);
float db = abs((2.0 * b1 - b2) - c0);
float dt = abs((2.0 * t1 - t2) - c0);
vec3 ce = getViewPosition(uv, c0).xyz;
vec3 dpdx = (dl < dr) ? ce - getViewPosition((uv - vec2(1.0 / size.x, 0.0)), l1).xyz
: -ce + getViewPosition((uv + vec2(1.0 / size.x, 0.0)), r1).xyz;
vec3 dpdy = (db < dt) ? ce - getViewPosition((uv - vec2(0.0, 1.0 / size.y)), b1).xyz
: -ce + getViewPosition((uv + vec2(0.0, 1.0 / size.y)), t1).xyz;
return normalize(cross(dpdx, dpdy));
}
void main() {
float depth = getDepth(vUv.xy);
vec3 normal = computeNormalFromDepth(vUv);
gl_FragColor = FRAGMENT_OUTPUT;
}`

};
Expand Down Expand Up @@ -580,4 +668,4 @@ function generateMagicSquare( size ) {
}


export { generateAoSampleKernelInitializer, generateMagicSquareNoise, AOShader, AODepthShader, AoBlendShader };
export { generateAoSampleKernelInitializer, generateMagicSquareNoise, AOShader, AoBlendShader, AODepthToNormalShader, AODepthShader };
8 changes: 4 additions & 4 deletions src/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ const scene = new THREE.Scene();
scene.background = new THREE.Color( 0xbfe3dd );
scene.environment = pmremGenerator.fromScene( new RoomEnvironment( renderer ), 0.04 ).texture;

const camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 100 );
camera.position.set( -8, 1.5, 0 );
const camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 40 );
camera.position.set( -12, 1.5, 0 );

const controls = new OrbitControls( camera, renderer.domElement );
controls.target.set( 0, 1.5, 0 );
Expand Down Expand Up @@ -99,8 +99,8 @@ gui.add( aoPass, 'output', {
'Diffuse': AOPass.OUTPUT.Diffuse,
'AO Only': AOPass.OUTPUT.AO,
'AO Only + Denoise': AOPass.OUTPUT.Denoise,
//'Depth': AOPass.OUTPUT.Depth,
//'Normal': AOPass.OUTPUT.Normal
'Depth': AOPass.OUTPUT.Depth,
'Normal': AOPass.OUTPUT.Normal
} ).onChange( function ( value ) {

aoPass.output = value;
Expand Down

0 comments on commit b715fd6

Please sign in to comment.